При формировании объемных печатных форм разработчики часто сталкиваются с задачей максимально плотно уместить данные на листе бумаги, чтобы сэкономить ресурсы. Однако попытки программно рассчитать, сколько строк поместится на страницу, приводят к странным цифрам, а использование стандартного метода ПроверитьВывод() на больших объемах данных вызывает катастрофическое падение производительности. Разберем по шагам, как платформа 1С работает с размерами табличного документа, выясним причины замедлений и рассмотрим эффективные способы оптимизации вывода на печать.
Чтобы понять, как 1С рассчитывает высоту листа, проанализируем базовые единицы измерения. В платформе 1С высота строки табличного документа задается не в миллиметрах и не в абстрактных пикселях, а в типографских пунктах. Один стандартный пункт равен ровно 0,3528 мм.
Посмотрим на пример с листом формата А4. Стандартная физическая высота листа А4 составляет 297 мм. Переведем это значение в пункты:
Но при печати мы никогда не используем лист от края до края. Принтеры требуют технологических отступов (полей). Если мы зададим стандартные поля сверху и снизу по 10 мм, то полезная площадь по высоте составит 277 мм. Переведем ее в пункты:
Теперь становится понятно, почему в экспериментах на пустой странице идеально помещается 78 строк с высотой 10. В сумме они дают 780 пунктов, что практически полностью заполняет полезную площадь листа А4 с учетом стандартных полей. Запомните этот принцип: для расчетов высоты оперируйте пунктами.
Многие разработчики жалуются, что метод ПроверитьВывод() возвращает ложь (строка не влезает), когда на странице визуально остается еще треть пустого места. Проанализируем ситуацию и выделим две главные причины такого поведения:
ПроверитьВывод() может оценивать габариты строк до применения этого сжатия.АвтоВысотаСтроки, программное обращение к высоте вернет либо ноль, либо максимальную высоту из конфигуратора. Алгоритм не знает фактическую высоту, пока текст не будет срендерен.Если вам все же необходимо оперировать миллиметрами, а не пунктами, рассмотрим несколько способов получения точных габаритов.
Способ 1: Использование объекта Рисунок
Мы можем вывести нужную область в рисунок, привязать его к области и запросить высоту:
Рисунок = ТабличныйДокумент.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Текст);
Рисунок.Расположить(ВыводимаяОбласть);
ВысотаВМилиметрах = Рисунок.Высота;
Свойство Высота у рисунка всегда возвращает значение в миллиметрах.
Способ 2: Объект РазмерСтраницы
Для получения стандартизированных габаритов листов в платформе предусмотрен системный объект РазмерСтраницы. Обратившись к нему (например, РазмерСтраницы.A4()), вы можете сразу получить свойства Ширина и Высота строго в миллиметрах, не прибегая к ручным расчетам.
Если документ состоит из одной-двух страниц, ПроверитьВывод() работает мгновенно. Однако по мере роста количества страниц в результирующем табличном документе происходит сильная деградация скорости. Платформе приходится пересчитывать границы переносов для всего огромного документа при каждом добавлении новой строки. На 100-200 страницах этот процесс может полностью повесить систему.
Решим эту проблему с помощью метода «Двух таблиц». Суть метода заключается в том, чтобы проверять вывод не на итоговом огромном документе, а на маленьком временном, содержащем только текущую страницу.
Разберем алгоритм по шагам:
ТабДокИтог (общий результат) и ТабДокСтраница (буфер для одной страницы).ТабДокСтраница.ПроверитьВывод(Область).ТабДокСтраница, и в ТабДокИтог (в итоговый документ добавляем без проверки, что экономит время).ТабДокСтраница.Очистить();ТабДокИтог горизонтальный разделитель: ТабДокИтог.ВывестиГоризонтальныйРазделительСтраниц();ТабДокСтраница и в ТабДокИтог.Такой подход гарантирует, что ПроверитьВывод() всегда работает только с объемом данных не больше одной страницы, и скорость формирования документа из 1000 страниц становится такой же быстрой, как и из 10 страниц.
Если структура вашего документа позволяет, можно полностью отказаться от функции ПроверитьВывод(), ускорив формирование в десятки раз. Рассмотрим метод пиксельной сетки.
Для этого в макете полностью отключается свойство автовысоты. Все ячейки делаются фиксированного минимального размера (например, высота строго 10,5 пунктов). Многострочный текст разбивается встроенными функциями форматирования строк самой платформы (нарезается на подстроки), и каждая подстрока выводится в отдельную строку фиксированной высоты.
Поскольку высота любой выводимой строки теперь известна заранее (10,5 пунктов), мы просто заводим числовой счетчик в цикле вывода. Как только сумма пунктов в счетчике приближается к 780 (максимальная вместимость А4 без полей), программа принудительно вставляет РазделительСтраниц и обнуляет счетчик. Этот математический подход требует больше усилий при верстке макета, но обеспечивает непревзойденную производительность при массовой печати биллинговых или складских документов.