При формировании печатных форм, таких как договоры, акты или официальные письма, разработчики часто сталкиваются с необходимостью идеального форматирования текста. Одной из наиболее распространенных задач является выравнивание текста «По ширине». Однако в платформе «1С:Предприятие» работа этого механизма имеет свои особенности, которые отличают её от привычных текстовых редакторов вроде Microsoft Word. В частности, последняя строка абзаца (или единственная строка в ячейке) упорно отказывается растягиваться от края до края, оставаясь прижатой к левой стороне.
В этой статье мы подробно разберем, почему так происходит, как устроен движок отрисовки текста в 1С и какие программные методы можно использовать для обхода этого ограничения.
Для начала проанализируем ситуацию с точки зрения типовых алгоритмов верстки. В большинстве систем обработки текста существует два похожих, но разных типа выравнивания:
Табличный документ 1С в значительной степени наследует логику Microsoft Excel. В этих программных продуктах реализован именно классический Justify. Как только система встречает символ конца абзаца или конец блока текста, она считает текущую строку «завершающей» и отключает для неё механизм распределения пробелов. Это считается стандартным поведением для табличных редакторов.
Рассмотрим подробнее, как платформа распознает, пора ли растягивать строку. Когда мы программно наполняем ячейку текстом, мы часто используем символ Символы.ПС (перевод строки). Для платформы этот символ является жестким маркером конца параграфа. Разберем ситуацию на примере:
Область = Макет.ПолучитьОбласть("СтрокаТекста");
ТекстДляВывода = "Это пример длинного текста, который должен быть идеально выровнен.";
Область.Параметры.ЗначениеЯчейки = ТекстДляВывода;
// Установка выравнивания программно
Область.Область().ГоризонтальноеПоложение = ГоризонтальноеПоложение.ПоШирине;
Даже если этот текст занимает ровно полторы строки в ячейке, первая строка будет растянута, а вторая (последняя) — нет. Если же вы программно обрезаете строку и добавляете разделитель страниц, как делал автор вопроса, система воспринимает каждую такую строку как отдельный законченный абзац. Именно поэтому «растягивание» не происходит: для 1С каждая ваша строка является «последней».
Поскольку стандартного свойства Распределенное выравнивание в 1С не существует, нам придется рассмотреть обходные пути. Проанализируем наиболее жизнеспособные варианты.
Иногда разработчики пытаются обмануть алгоритм, подставляя в конец строки символы, которые заставят систему думать, что строка еще не закончена. Однако 1С достаточно эффективно отсекает пустые символы в конце строки при отрисовке. Тем не менее, можно попробовать заменить обычные пробелы на неразрывные (Символы.НПП), но это скорее поможет предотвратить нежелательный перенос слова, чем растянуть строку.
Это наиболее сложный, но потенциально результативный метод. Его суть заключается в том, чтобы самостоятельно вычислить, сколько лишних пробелов нужно вставить между словами в последней строке, чтобы она визуально коснулась правого края. Посмотрим на алгоритм реализации:
ШиринаСтрокиВПикселях(), поэтому разработчики часто используют объекты типа COMОбъект("Попытка_использовать_скрытое_окно_IE") или сторонние компоненты, но в чистой платформе 1С это можно сделать только приблизительно, зная среднюю ширину символа.Пример логики добавления пробелов:
Функция РастянутьСтроку(Знач ИсходнаяСтрока, ЦелеваяШирина)
МассивСлов = СтрРазделить(ИсходнаяСтрока, " ");
Если МассивСлов.Количество() < 2 Тогда
Возврат ИсходнаяСтрока;
КонецЕсли;
// Вставляем дополнительные пробелы между словами в цикле,
// пока строка визуально не совпадет с нужной шириной
// (Требует использования моноширинного шрифта для точности)
Для к = 1 По КоличествоНужныхПробелов Цикл
Индекс = к % (МассивСлов.Количество() - 1);
МассивСлов[Индекс] = МассивСлов[Индекс] + " ";
КонецЦикла;
Возврат СтрСоединить(МассивСлов, " ");
КонецФункции
Важное примечание: Этот метод корректно работает только с моноширинными шрифтами (например, Courier New). При использовании пропорциональных шрифтов (типа Arial или Times New Roman) ширина букв "i" и "W" сильно различается, и точно рассчитать заполнение строки практически невозможно.
Автор вопроса упоминал, что он формирует строку по словам и проверяет, помещается ли она на страницу. Для этого обычно используется метод ПроверитьВывод(). Проанализируем, почему этот метод не помогает в вопросе выравнивания. Функция ПроверитьВывод() лишь сообщает, уместится ли переданный массив областей на оставшейся части листа. Она никак не влияет на то, как внутри этих областей будет распределен текст.
Если вы разделяете текст вручную, чтобы обеспечить корректный разрыв страниц, вы фактически берете на себя роль движка верстки. В таком случае, чтобы добиться растяжения последней строки на каждой странице, вам придется либо отказаться от выравнивания «По ширине» в пользу ручного управления пробелами, либо смириться с тем, что последняя строка перед разрывом страницы будет выровнена по левому краю.
Нужно учитывать еще один критический фактор. Даже если на экране в режиме редактирования вам удалось добиться визуального растяжения строки с помощью пробелов, при выводе на печать результат может измениться. Это происходит потому, что:
Подводя итог, можно констатировать, что штатного способа сделать Distributed alignment для последней строки в табличном документе 1С не существует. Это ограничение платформенного движка, ориентированного на логику электронных таблиц, а не текстовых процессоров.
Если задача стоит критически остро (например, жесткие требования к оформлению юридических документов), рекомендуем следующие шаги:
Courier New. Это позволит вам программно вычислить количество пробелов между словами для имитации растяжения.Таким образом, мы выяснили, что поведение 1С в данном вопросе является ожидаемым. Для достижения нестандартного результата требуется либо сложная программная обработка строк, либо смена инструмента формирования печатной формы.