Есть фиксированный макет, разработанный для печати этикетки фиксированного размера. Текст, который выводится в этот макет, может иметь различную, плохо прогнозируемую длину.
Если мы выберем маленький размер шрифта для короткого текста, возникнет резонное замечание – а зачем тут столько пустого места?
Если выберем шрифт больше и попадется длинный текст – возникает вопрос еще более резонный: а что тут напечатано? Часть текста пропала...
Задача озвучивалась не раз. И наверняка много раз решена. Например, Поместится ли текст в ячейке? (с примерами использования: авторазмер шрифта, перенос строк)
Но, увы, этот способ очень медленный.
Если нужно вывести 1-3 простых ценника – это идеальный вариант. Если большой набор этикеток выводит Ответственный или Важный менеджер и это займет у него 30 минут – тоже не вопрос: он "работает". Но если работник с ТСД нажимает кнопку ОК и больше минуты не получает отклика – этот способ совершенно неприемлем.
Не смотря на простоту постановки, задача оказалась весьма сложной.
Конечно, есть вообще уникально-элементарное решение:
Если СтрДлина(Текст) < 20
Ячейка.Шрифт = Новый Шрифт(Ячейка.Шрифт,,СтолькоТо20)
ИначеЕсли СтрДлина(Текст) < 30
Ячейка.Шрифт = Новый Шрифт(Ячейка.Шрифт,,СтолькоТо30)
ИначеЕсли
...
Но это все нужно писать под каждый макет, под каждую ячейку отдельно. Это работает кое-как. И это крайне утомительно, скучно и грустно...
Поэтому пришлось искать свое, рабочее решение.
Самый простой способ (который и приводится в примере) – это построить таблицу ширин символов и высот строк для каждого размера шрифта.
Основная проблема в том, что размер символа не линейно зависит от размера шрифта. Множественные попытки применить математику для расчета или прогнозирования ширин и высот не увенчались успехом.
И вот наступил момент, когда стало понятно: время, потраченное на решение задачи, превышает удовольствие от ее решения (иногда эти величины соизмеримы. Особенно когда тратишь на это свое свободное время).
Следующим этапом был вывод:
– если не ставить задачу так строго, то в каком-то очень практичном приближении задачу решить все-таки можно.
Причем, тут нет никакой эмпирики. Все очень строго. Но требует статичного массива информации. (Кто постарше - помните "Таблицы Брадиса"?)
В результате появилась достаточно простая схема: каждый символ имеет некую ширину, которую можно определить. Каждая строка имеет определенную высоту, не зависящую от набора символов в ней. Размер ячейки определяется как: Ширина = (сумма ширин символов строки) + (поля по ширине); Высота = (высота одной строки)*(количество строк) + (вертикальные поля).
Все эти величины удалось определить различными способами (в том числе помог подсмотренный в упомянутой статье метод с рисунком).
К публикации прилагается тестовый фрагмент таблицы размеров шрифта Arial (обычный, курсив, полужирный, полужирный курсив) от 8 до 48.
Ширины расчитаны для букв латиницы, кириллицы (в т.ч. украинских Ї, Ґ), цифр и основоного набора символов.
Далее – просто ремесло.
Набор предложенных функций реализует следующий механизм:
1. Как и в стандартной схеме мы
1.1. создаем/получаем табличный документ
1.2. получаем/создаем макет
1.3. наполняем макет информацией (заполняем значения параметров и проч.)
1.4. выводим/присоединяем область макета в конечный документ
2. Стандартные методы табличного документа "Вывести" и "Присоединить" заменяются функциями "ВывестиИПодогнатьТекст" и "ПрисоединитьИПодогнатьТекст".
В качестве параметров передаются:
ТабДокПриемник - документ, в который собственно осуществляется вывод
ТабДокИсточник - область макета с заполненными параметрами (или другой табличный документ),
Ячейки - строка с именами или адресами ячеек, для которых необходимо подобрать размер шрифта
Минимальный допустимый размер шрифта
УдалятьПробелыПереноса - (см.далее)
Обязательными являются только два первых параметра.
Если не указаны имена ячеек – подгоняется текст во всех ячейках источника, имеющих "ТипЗаполнения" "Параметр" или "Шаблон".
Если не указан минимальный размер – будет взят минимальный размер, присутствующий в таблице ширин (он же будет использован, если в параметре передано меньшее значение)
УдалятьПробелыПереноса. Кому-то этот параметр покажется смешным и бесполезным. Но я не смог его проигнорировать (тем более что реализуется его назначение в рамках основной задачи очень просто). Суть в следующем.
Например, мы выводим в ячейку несколько однотипных значений (например, цифровых артикулов). По ширине в строках вмещается одинаковое их количество. Если в ячейке установлены размещение текста "Переносить" и Горизонтальное выравнивание Центр, то получится, что последняя строка несколько смещается вправо (см. Рис). Если же заменить пробелы, по которым происходят переносы строк, символами ПС – картинка выглядит гораздо приятнее.
В качестве максимального (с него начинается расчет) принимается размер, указанный разработчиком/дизайнером в макете.
В алгоритме принципиально не учитываются стандартные вертикальные поля и, где это возможно – горизонтальные.
Если возникнет желание их учитывать – в коде есть необходимые комментарии (сами значения в таблице ширин присутствуют).
Ячейки с типом размещения текста "Забивать" и "Обрезать" - не рассматриваются.
Таблицу ширин можно загружать из файла или из справочника. В модуле обработки необходимо внести изменения в шаблоне функции загрузки таблицы ширин.
Я храню ее в глобальной переменной и загружаю при первом вызове процедуры подбора (хотя и не уверен, что это хорошо. подскажите, гуру).
Предложение загрузить файл ширин выводится при открытии обработки. Но это можно зделать и позже по кнопке "Прочитать параметры шрифтов". Также на форме есть две кнопки: Тест1 (подгоняет произвольный текст в ячейку таб.документа на форме) и Тест2 (выводит несколько примеров на основании макета в табличный документ).
Вот, по сути, и все.
В прилагаемой обработке показан упрощенный алгоритм (для облегчения понимания).
В рабочей версии присутствует дополнительный функционал:
* коэффициент высоты (позволяет принудительно управлять размером вертикальных полей)
* интерполяция размера (если в таблице ширин отсутствует необходимый размер)
Не уверен, что этот функционал необходим. Это я добавлял уже под собственные задачи.
Пробуйте. Могут возникнуть неточности при других версиях шрифта и специфических драйверах принтеров.
Шлите скриншоты, если что-то не так.
Съешь еще этих мягких французских булок, да выпей чаю. 1234567890