Как программно уместить табличный документ на одну страницу по высоте в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе разработки печатных форм в системе 1С:Предприятие программисты часто сталкиваются с ситуацией, когда стандартного свойства АвтоМасштаб оказывается недостаточно. Проблема заключается в том, что механизм автоматического масштабирования в 1С работает преимущественно «по ширине». Если ваш документ имеет фиксированную ширину, но из-за динамического изменения высоты строк начинает выходить за пределы одной страницы вниз, платформа не уменьшит его масштаб автоматически, чтобы «втиснуть» всё на один лист. Рассмотрим, как решить эту задачу программно, используя доступные инструменты платформы.

Разберем проблему: почему АвтоМасштаб не помогает?

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

Для решения этой задачи нам придется вручную управлять свойством МасштабПечати. Это числовое значение, определяющее масштаб в процентах (от 10 до 100 и более). Наша цель — найти такое максимальное значение масштаба, при котором количество страниц документа будет равно единице.

Использование метода КоличествоСтраниц() вместо ПроверитьВывод()

В обсуждениях часто упоминается метод ПроверитьВывод(). Этот метод возвращает булево значение, сообщающее, поместится ли переданный массив областей в текущую страницу. Однако, как показывает практика, при динамическом изменении масштаба в цикле этот метод может вести себя нестабильно из-за особенностей кэширования макета. Более надежным способом является использование функции КоличествоСтраниц().

Рассмотрим пошагово алгоритм подбора масштаба:

  1. Убедимся, что свойство АвтоМасштаб установлено в значение Ложь, так как ручное управление масштабом несовместимо с автоматическим.
  2. Установим начальный масштаб (например, 100%).
  3. В цикле будем уменьшать масштаб на фиксированный шаг (например, на 1%), пока количество страниц не станет равным единице.

Проанализируем пример кода для реализации этого подхода:


ТабДок = Новый ТабличныйДокумент;
// ... Заполнение табличного документа ...
ТабДок.АвтоМасштаб = Ложь;
ТекущийМасштаб = 100;

Пока ТабДок.КоличествоСтраниц() > 1 И ТекущийМасштаб > 10 Цикл
    ТекущийМасштаб = ТекущийМасштаб - 1;
    ТабДок.МасштабПечати = ТекущийМасштаб;
КонецЦикла;

Этот метод прост, но имеет существенный недостаток: скорость работы. Каждое обращение к методу КоличествоСтраниц() заставляет платформу пересчитывать геометрию всего документа с учетом текущего масштаба и настроек принтера. Если документ большой, а масштаб придется снижать до 60-70%, цикл может затянуться на несколько секунд.

Оптимизация через алгоритм «Бинарного поиска»

Выясним, как ускорить процесс подбора. Вместо линейного перебора (100, 99, 98...) мы можем применить метод деления отрезка пополам. Это позволит найти оптимальный масштаб за 6–7 итераций вместо 40–50. Рассмотрим реализацию бинарного поиска для масштаба:


НижнийПредел = 10; // Минимально читаемый масштаб
ВерхнийПредел = 100;
ОптимальныйМасштаб = 100;

Пока НижнийПредел <= ВерхнийПредел Цикл
    СреднийМасштаб = Цел((НижнийПредел + ВерхнийПредел) / 2);
    ТабДок.МасштабПечати = СреднийМасштаб;
    
    Если ТабДок.КоличествоСтраниц() > 1 Тогда
        ВерхнийПредел = СреднийМасштаб - 1;
    Иначе
        ОптимальныйМасштаб = СреднийМасштаб;
        НижнийПредел = СреднийМасштаб + 1;
    КонецЕсли;
КонецЦикла;

ТабДок.МасштабПечати = ОптимальныйМасштаб;

В данном примере мы сужаем диапазон поиска, каждый раз проверяя «середину». Если при 50% документ влезает на одну страницу, мы пытаемся его увеличить, проверяя диапазон 51-100%. Если не влезает — уменьшаем, проверяя 10-49%.

Влияние настроек принтера и кэширования

Важно помнить, что 1С рассчитывает количество страниц на основе параметров текущего принтера, установленного в системе. Если на сервере (в случае выполнения кода на стороне сервера) принтер по умолчанию не установлен или имеет специфические поля, результаты работы КоличествоСтраниц() могут отличаться от того, что пользователь увидит при печати.

Рекомендация: перед началом расчетов явно задайте параметры страницы, такие как поля (ПолеСлева, ПолеСправа и т.д.) и ориентацию. Это гарантирует, что расчеты будут производиться в предсказуемом контексте.


ТабДок.ОриентацияСтраницы = ОриентацияСтраницы.Портрет;
ТабДок.ПолеСлева = 10;
ТабДок.ПолеСправа = 10;
ТабДок.ПолеСверху = 10;
ТабДок.ПолеСнизу = 10;
ТабДок.ИмяПринтера = "ИмяВашегоПринтера"; // Если известно

Дополнительные приемы

Если после уменьшения масштаба до определенного предела (например, 70%) текст становится нечитаемым, стоит рассмотреть смену ориентации страницы. Посмотрим на алгоритм: сначала проверяем, помещается ли документ в портретной ориентации при 100%. Если нет — пробуем сменить ориентацию на ОриентацияСтраницы.Ландшафт. И только если в ландшафте документ всё равно не влезает на одну страницу, запускаем цикл уменьшения масштаба.

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

Подведем итог: наиболее эффективным и надежным способом «отловить» масштаб для вписывания документа по высоте является использование метода КоличествоСтраниц() в связке с алгоритмом бинарного поиска и предварительной жесткой установкой полей страницы.

← На главную