Почему не работает метод табличного документа ПроверитьВывод в ориентации Ландшафт и как это исправить?

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия
← На главную

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

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

Суть проблемы: когда ПроверитьВывод ошибается

Рассмотрим типичную ситуацию. Программист формирует табличный документ, устанавливает ориентацию страницы в значение ОриентацияСтраницы.Ландшафт и выводит строки в цикле, проверяя, поместится ли следующая порция данных. Если метод ПроверитьВывод возвращает Ложь, выводится заголовок таблицы (шапка) на новом листе. Проблема в том, что в ландшафтном режиме алгоритм расчета высоты страницы в 1С начинает давать погрешность. Например, метод считает, что на лист влезет 20 строк, но фактически помещается только 17. Оставшиеся 3 строки "вылетают" на новый лист, создавая некрасивый разрыв.

Проанализируем программный код, который часто приводит к таким последствиям:


ТабДокумент = Новый ТабличныйДокумент;
Макет = ПолучитьМакет("Макет");
// Установка параметров
ТабДокумент.ПолеСверху = 0;
ТабДокумент.ПолеСлева = 0;
ТабДокумент.ПолеСнизу = 0;
ТабДокумент.ПолеСправа = 0;
ТабДокумент.АвтоМасштаб = Истина;
ТабДокумент.ОриентацияСтраницы = ОриентацияСтраницы.Ландшафт;

Как показывает практика, именно сочетание нулевых полей и ландшафтной ориентации является критическим фактором для возникновения ошибки.

Решение №1: Установка корректных значений полей

Выясним причину, по которой нулевые поля (ПолеСнизу = 0) мешают правильному расчету. Любой принтер имеет так называемые "непечатные зоны" — физические ограничения механизмов подачи бумаги. Когда мы устанавливаем поля в 0, 1С пытается использовать всю теоретическую поверхность листа. Однако метод ПроверитьВывод ориентируется на метрики драйвера текущего принтера. В режиме "Ландшафт" драйверы часто передают некорректные или специфические данные о границах печати.

Практическое решение: установите программно все поля документа в значение не менее 10 мм. Это создаст необходимый "буфер", который нивелирует разницу между расчетами платформы и реальностью драйвера принтера.


ТабДокумент.ПолеСверху = 10;
ТабДокумент.ПолеСлева = 10;
ТабДокумент.ПолеСнизу = 10;
ТабДокумент.ПолеСправа = 10;

После установки таких параметров метод ПроверитьВывод начинает получать от системы более предсказуемые данные о доступной высоте страницы, и проблема с "лишними" строками обычно исчезает.

Решение №2: Влияние свойства АвтоМасштаб

Проанализируем работу свойства АвтоМасштаб. Когда оно установлено в значение Истина, платформа 1С пытается динамически сжать документ так, чтобы он уместился по ширине страницы. В ландшафтной ориентации ширина значительно больше, чем в портретной. Если ваш макет по ширине близок к границе листа, 1С может применить микро-масштабирование (например, 98% от оригинала).

Проблема в том, что метод ПроверитьВывод иногда выполняет расчет до того, как окончательный коэффициент масштабирования будет применен к высоте строк. Это приводит к накоплению микроскопических погрешностей в несколько пикселей на каждую строку. При выводе 50 строк эти пиксели суммируются в миллиметры, которых как раз и "не хватает" последней строке.

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

Решение №3: Порядок инициализации свойств документа

Существует важный нюанс в последовательности действий разработчика. Выясним, когда именно нужно задавать ориентацию страницы. Если вы сначала вывели хотя бы одну область в ТабличныйДокумент, а только потом установили ОриентацияСтраницы.Ландшафт, расчеты метода ПроверитьВывод могут быть инициализированы по параметрам "Портрета", которые кэшируются внутри объекта.

Правильный алгоритм действий должен быть следующим:

  1. Создать объект ТабличныйДокумент.
  2. Сразу установить ориентацию, поля, имя принтера (если известно).
  3. Только после этого начинать вывод областей через Вывести() или Присоединить().

Решение №4: Ключ параметров печати и пользовательские настройки

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

Для отладки попробуйте закомментировать строку:

// ТабДокумент.КлючПараметровПечати = "МояУникальнаяПечатнаяФорма";

Если после этого расчет стал верным, значит, в системе сохранились некорректные старые настройки. Вам нужно либо сбросить их, либо использовать новый уникальный ключ.

Решение №5: Использование КоличествоСтраниц как альтернатива

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

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

  1. Выводим область в табличный документ.
  2. Запоминаем текущее количество страниц: ТекущееКолСтраниц = ТабДок.КоличествоСтраниц();.
  3. Выводим следующую строку (или группу строк).
  4. Снова проверяем количество страниц.
  5. Если оно увеличилось, значит, произошел перенос. Мы должны удалить последнюю выведенную область (или вставить разделитель перед ней) и вывести шапку.

Этот метод работает на основе уже фактически отрисованной графики документа и практически никогда не ошибается, так как он не "предсказывает" будущее, а констатирует факт перехода на новый лист.

Итоговый пример надежного кода

Соберем все наши выводы в один надежный блок кода, который минимизирует риск ошибки в ландшафтном режиме:


ТабДок = Новый ТабличныйДокумент;
ТабДок.ОриентацияСтраницы = ОриентацияСтраницы.Ландшафт;

// Устанавливаем поля не менее 10мм для стабильности
ТабДок.ПолеСверху = 10;
ТабДок.ПолеСнизу = 10;
ТабДок.ПолеСлева = 10;
ТабДок.ПолеСправа = 10;

// Очищаем ключ или используем новый для исключения влияния кэша
ТабДок.КлючПараметровПечати = "УникальныйКлюч_М4_Ландшафт";

Макет = ПолучитьМакет("Макет");
ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");

// Выводим первую шапку
ТабДок.Вывести(ОбластьШапка);

Для Каждого СтрокаДанных Из ТЧ Цикл
    // Создаем массив областей для проверки
    МассивОбластей = Новый Массив;
    МассивОбластей.Добавить(ОбластьСтрока);
    
    // Важно: ПроверитьВывод вызываем ДО вывода самой строки
    Если Не ТабДок.ПроверитьВывод(МассивОбластей) Тогда
        ТабДок.ВывестиГоризонтальныйРазделительСтраниц();
        ТабДок.Вывести(ОбластьШапка);
    КонецЕсли;
    
    // Заполнение параметров и вывод
    ОбластьСтрока.Параметры.Заполнить(СтрокаДанных);
    ТабДок.Вывести(ОбластьСтрока);
КонецЦикла;

// Включаем авто-масштаб в самом конце
ТабДок.АвтоМасштаб = Истина;
ТабДок.Показать();

Подведем итог: основная причина проблем с методом ПроверитьВывод в ландшафтном режиме кроется в "нулевых" полях и конфликтах с драйвером принтера. Установка полей в 10 мм и правильный порядок инициализации свойств документа решают эту проблему в 90% случаев. В самых сложных ситуациях всегда можно прибегнуть к методу КоличествоСтраниц() для получения гарантированного результата.

← На главную