Как определить высоту листа А4 в табличном документе 1С и оптимизировать ПроверитьВывод()?

Программист IT и автоматизация бизнеса
← На главную

При формировании объемных печатных форм разработчики часто сталкиваются с задачей максимально плотно уместить данные на листе бумаги, чтобы сэкономить ресурсы. Однако попытки программно рассчитать, сколько строк поместится на страницу, приводят к странным цифрам, а использование стандартного метода ПроверитьВывод() на больших объемах данных вызывает катастрофическое падение производительности. Разберем по шагам, как платформа 1С работает с размерами табличного документа, выясним причины замедлений и рассмотрим эффективные способы оптимизации вывода на печать.

Единицы измерения в 1С: почему высота строк не совпадает с миллиметрами

Чтобы понять, как 1С рассчитывает высоту листа, проанализируем базовые единицы измерения. В платформе 1С высота строки табличного документа задается не в миллиметрах и не в абстрактных пикселях, а в типографских пунктах. Один стандартный пункт равен ровно 0,3528 мм.

Посмотрим на пример с листом формата А4. Стандартная физическая высота листа А4 составляет 297 мм. Переведем это значение в пункты:

Но при печати мы никогда не используем лист от края до края. Принтеры требуют технологических отступов (полей). Если мы зададим стандартные поля сверху и снизу по 10 мм, то полезная площадь по высоте составит 277 мм. Переведем ее в пункты:

Теперь становится понятно, почему в экспериментах на пустой странице идеально помещается 78 строк с высотой 10. В сумме они дают 780 пунктов, что практически полностью заполняет полезную площадь листа А4 с учетом стандартных полей. Запомните этот принцип: для расчетов высоты оперируйте пунктами.

Почему ПроверитьВывод() работает непредсказуемо и оставляет пустоты

Многие разработчики жалуются, что метод ПроверитьВывод() возвращает ложь (строка не влезает), когда на странице визуально остается еще треть пустого места. Проанализируем ситуацию и выделим две главные причины такого поведения:

  1. Влияние автомасштаба. Часто в параметрах страницы табличного документа установлен масштаб «По ширине страницы». Если формируемая таблица хотя бы на долю миллиметра шире физического листа, 1С принудительно сжимает ее пропорционально перед печатью. Из-за этого высота строк физически уменьшается, и на лист влезает больше данных. Однако программная проверка ПроверитьВывод() может оценивать габариты строк до применения этого сжатия.
  2. Коварство автовысоты. Если для ячеек макета установлено свойство АвтоВысотаСтроки, программное обращение к высоте вернет либо ноль, либо максимальную высоту из конфигуратора. Алгоритм не знает фактическую высоту, пока текст не будет срендерен.

Как программно получить высоту области в миллиметрах

Если вам все же необходимо оперировать миллиметрами, а не пунктами, рассмотрим несколько способов получения точных габаритов.

Способ 1: Использование объекта Рисунок
Мы можем вывести нужную область в рисунок, привязать его к области и запросить высоту:


Рисунок = ТабличныйДокумент.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Текст);
Рисунок.Расположить(ВыводимаяОбласть);
ВысотаВМилиметрах = Рисунок.Высота;

Свойство Высота у рисунка всегда возвращает значение в миллиметрах.

Способ 2: Объект РазмерСтраницы
Для получения стандартизированных габаритов листов в платформе предусмотрен системный объект РазмерСтраницы. Обратившись к нему (например, РазмерСтраницы.A4()), вы можете сразу получить свойства Ширина и Высота строго в миллиметрах, не прибегая к ручным расчетам.

Оптимизация ПроверитьВывод() при формировании сотен страниц

Если документ состоит из одной-двух страниц, ПроверитьВывод() работает мгновенно. Однако по мере роста количества страниц в результирующем табличном документе происходит сильная деградация скорости. Платформе приходится пересчитывать границы переносов для всего огромного документа при каждом добавлении новой строки. На 100-200 страницах этот процесс может полностью повесить систему.

Решим эту проблему с помощью метода «Двух таблиц». Суть метода заключается в том, чтобы проверять вывод не на итоговом огромном документе, а на маленьком временном, содержащем только текущую страницу.

Разберем алгоритм по шагам:

  1. Создаем два табличных документа: ТабДокИтог (общий результат) и ТабДокСтраница (буфер для одной страницы).
  2. Берем очередную строку/область для вывода и проверяем ее на маленьком документе ТабДокСтраница.ПроверитьВывод(Область).
  3. Если область помещается — добавляем её и в ТабДокСтраница, и в ТабДокИтог (в итоговый документ добавляем без проверки, что экономит время).
  4. Если область не помещается:
    • Очищаем буфер: ТабДокСтраница.Очистить();
    • Добавляем в ТабДокИтог горизонтальный разделитель: ТабДокИтог.ВывестиГоризонтальныйРазделительСтраниц();
    • Выводим текущую область в очищенный ТабДокСтраница и в ТабДокИтог.

Такой подход гарантирует, что ПроверитьВывод() всегда работает только с объемом данных не больше одной страницы, и скорость формирования документа из 1000 страниц становится такой же быстрой, как и из 10 страниц.

Альтернативный подход: Пиксельная сетка без ПроверитьВывод

Если структура вашего документа позволяет, можно полностью отказаться от функции ПроверитьВывод(), ускорив формирование в десятки раз. Рассмотрим метод пиксельной сетки.

Для этого в макете полностью отключается свойство автовысоты. Все ячейки делаются фиксированного минимального размера (например, высота строго 10,5 пунктов). Многострочный текст разбивается встроенными функциями форматирования строк самой платформы (нарезается на подстроки), и каждая подстрока выводится в отдельную строку фиксированной высоты.

Поскольку высота любой выводимой строки теперь известна заранее (10,5 пунктов), мы просто заводим числовой счетчик в цикле вывода. Как только сумма пунктов в счетчике приближается к 780 (максимальная вместимость А4 без полей), программа принудительно вставляет РазделительСтраниц и обнуляет счетчик. Этот математический подход требует больше усилий при верстке макета, но обеспечивает непревзойденную производительность при массовой печати биллинговых или складских документов.

← На главную