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