Разработка печатных форм в системе 1С:Предприятие — это процесс, требующий высокой точности. Одной из самых распространенных задач является вывод табличного документа с повторением "шапки" на каждой новой странице. Для этого традиционно используется метод ПроверитьВывод. Однако многие разработчики сталкиваются с тем, что в режиме Ландшафт (альбомная ориентация) этот метод начинает вести себя непредсказуемо: он ошибочно сообщает, что строки помещаются на страницу, хотя при фактической печати или просмотре они переносятся на следующий лист. В результате мы получаем "разорванные" таблицы и пустые пространства на страницах.
В этой статье мы подробно разберем, почему возникает эта проблема, как на нее влияют настройки принтера и полей, и какими способами можно добиться идеального выравнивания страниц.
Рассмотрим типичную ситуацию. Программист формирует табличный документ, устанавливает ориентацию страницы в значение ОриентацияСтраницы.Ландшафт и выводит строки в цикле, проверяя, поместится ли следующая порция данных. Если метод ПроверитьВывод возвращает Ложь, выводится заголовок таблицы (шапка) на новом листе. Проблема в том, что в ландшафтном режиме алгоритм расчета высоты страницы в 1С начинает давать погрешность. Например, метод считает, что на лист влезет 20 строк, но фактически помещается только 17. Оставшиеся 3 строки "вылетают" на новый лист, создавая некрасивый разрыв.
Проанализируем программный код, который часто приводит к таким последствиям:
ТабДокумент = Новый ТабличныйДокумент;
Макет = ПолучитьМакет("Макет");
// Установка параметров
ТабДокумент.ПолеСверху = 0;
ТабДокумент.ПолеСлева = 0;
ТабДокумент.ПолеСнизу = 0;
ТабДокумент.ПолеСправа = 0;
ТабДокумент.АвтоМасштаб = Истина;
ТабДокумент.ОриентацияСтраницы = ОриентацияСтраницы.Ландшафт;
Как показывает практика, именно сочетание нулевых полей и ландшафтной ориентации является критическим фактором для возникновения ошибки.
Выясним причину, по которой нулевые поля (ПолеСнизу = 0) мешают правильному расчету. Любой принтер имеет так называемые "непечатные зоны" — физические ограничения механизмов подачи бумаги. Когда мы устанавливаем поля в 0, 1С пытается использовать всю теоретическую поверхность листа. Однако метод ПроверитьВывод ориентируется на метрики драйвера текущего принтера. В режиме "Ландшафт" драйверы часто передают некорректные или специфические данные о границах печати.
Практическое решение: установите программно все поля документа в значение не менее 10 мм. Это создаст необходимый "буфер", который нивелирует разницу между расчетами платформы и реальностью драйвера принтера.
ТабДокумент.ПолеСверху = 10;
ТабДокумент.ПолеСлева = 10;
ТабДокумент.ПолеСнизу = 10;
ТабДокумент.ПолеСправа = 10;
После установки таких параметров метод ПроверитьВывод начинает получать от системы более предсказуемые данные о доступной высоте страницы, и проблема с "лишними" строками обычно исчезает.
Проанализируем работу свойства АвтоМасштаб. Когда оно установлено в значение Истина, платформа 1С пытается динамически сжать документ так, чтобы он уместился по ширине страницы. В ландшафтной ориентации ширина значительно больше, чем в портретной. Если ваш макет по ширине близок к границе листа, 1С может применить микро-масштабирование (например, 98% от оригинала).
Проблема в том, что метод ПроверитьВывод иногда выполняет расчет до того, как окончательный коэффициент масштабирования будет применен к высоте строк. Это приводит к накоплению микроскопических погрешностей в несколько пикселей на каждую строку. При выводе 50 строк эти пиксели суммируются в миллиметры, которых как раз и "не хватает" последней строке.
Рекомендация: попробуйте временно отключить АвтоМасштаб и проверить работу метода. Если без него все работает корректно, значит, проблема в масштабировании. В таком случае можно устанавливать АвтоМасштаб = Истина только в самом конце формирования документа, непосредственно перед методом Показать().
Существует важный нюанс в последовательности действий разработчика. Выясним, когда именно нужно задавать ориентацию страницы. Если вы сначала вывели хотя бы одну область в ТабличныйДокумент, а только потом установили ОриентацияСтраницы.Ландшафт, расчеты метода ПроверитьВывод могут быть инициализированы по параметрам "Портрета", которые кэшируются внутри объекта.
Правильный алгоритм действий должен быть следующим:
ТабличныйДокумент.Вывести() или Присоединить().Часто программисты забывают о свойстве КлючПараметровПечати. Это свойство позволяет системе запоминать настройки печати (поля, масштаб, ориентацию), которые пользователь выбрал вручную в окне предпросмотра. Рассмотрим ситуацию: вы в коде написали ОриентацияСтраницы.Ландшафт, но пользователь когда-то ранее сохранил для этого отчета настройки "Портрет". Система может приоритетно взять настройки из кэша пользователя, что полностью сломает логику ПроверитьВывод.
Для отладки попробуйте закомментировать строку:
// ТабДокумент.КлючПараметровПечати = "МояУникальнаяПечатнаяФорма";
Если после этого расчет стал верным, значит, в системе сохранились некорректные старые настройки. Вам нужно либо сбросить их, либо использовать новый уникальный ключ.
Если метод ПроверитьВывод продолжает ошибаться (что иногда случается на специфических драйверах терминальных серверов), мы можем использовать более надежный, хотя и чуть более медленный способ. Это метод КоличествоСтраниц().
Разберем этот алгоритм по шагам:
ТекущееКолСтраниц = ТабДок.КоличествоСтраниц();.Этот метод работает на основе уже фактически отрисованной графики документа и практически никогда не ошибается, так как он не "предсказывает" будущее, а констатирует факт перехода на новый лист.
Соберем все наши выводы в один надежный блок кода, который минимизирует риск ошибки в ландшафтном режиме:
ТабДок = Новый ТабличныйДокумент;
ТабДок.ОриентацияСтраницы = ОриентацияСтраницы.Ландшафт;
// Устанавливаем поля не менее 10мм для стабильности
ТабДок.ПолеСверху = 10;
ТабДок.ПолеСнизу = 10;
ТабДок.ПолеСлева = 10;
ТабДок.ПолеСправа = 10;
// Очищаем ключ или используем новый для исключения влияния кэша
ТабДок.КлючПараметровПечати = "УникальныйКлюч_М4_Ландшафт";
Макет = ПолучитьМакет("Макет");
ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
// Выводим первую шапку
ТабДок.Вывести(ОбластьШапка);
Для Каждого СтрокаДанных Из ТЧ Цикл
// Создаем массив областей для проверки
МассивОбластей = Новый Массив;
МассивОбластей.Добавить(ОбластьСтрока);
// Важно: ПроверитьВывод вызываем ДО вывода самой строки
Если Не ТабДок.ПроверитьВывод(МассивОбластей) Тогда
ТабДок.ВывестиГоризонтальныйРазделительСтраниц();
ТабДок.Вывести(ОбластьШапка);
КонецЕсли;
// Заполнение параметров и вывод
ОбластьСтрока.Параметры.Заполнить(СтрокаДанных);
ТабДок.Вывести(ОбластьСтрока);
КонецЦикла;
// Включаем авто-масштаб в самом конце
ТабДок.АвтоМасштаб = Истина;
ТабДок.Показать();
Подведем итог: основная причина проблем с методом ПроверитьВывод в ландшафтном режиме кроется в "нулевых" полях и конфликтах с драйвером принтера. Установка полей в 10 мм и правильный порядок инициализации свойств документа решают эту проблему в 90% случаев. В самых сложных ситуациях всегда можно прибегнуть к методу КоличествоСтраниц() для получения гарантированного результата.