Каждый разработчик 1С рано или поздно сталкивается с нюансами верстки печатных форм. Одна из классических проблем — поведение платформы при использовании свойства ПовторятьПриПечатиСтроки. Мы настраиваем повторяющуюся шапку таблицы для удобства чтения многостраничных документов. Однако, если строки таблицы полностью напечатаны на предыдущих страницах, а на последнюю страницу переносится исключительно подвал (например, итоговые суммы, подписи сторон и расшифровки), платформа автоматически выведет шапку таблицы прямо перед подвалом. Это выглядит неэстетично и непрофессионально: пустая шапка таблицы, под которой сразу идут подписи.
В этой статье мы подробно разберем, почему возникает данная проблема, и рассмотрим несколько эффективных способов ее решения: от простых декларативных настроек макета до полного программного контроля вывода страниц.
Проанализируем логику работы платформы 1С:Предприятие. Механизм ПовторятьПриПечатиСтроки работает линейно. Когда табличный документ формируется и отправляется на печать, платформа разбивает его на страницы на основе физических размеров листа и настроек принтера. Если очередная выводимая область (в нашем случае подвал) не помещается на текущем листе, система принудительно осуществляет разрыв страницы.
Начав новую страницу, платформа считывает настройки табличного документа. Видя, что для таблицы задана область повторения строк, система автоматически выводит ее вверху нового листа. Платформа не анализирует структуру документа глубже и не знает, что далее последуют не строки таблицы, а завершающий подвал. Для нее это просто продолжение единой табличной области.
Выясним, как решить проблему минимальными усилиями без написания сложного кода. Платформа предоставляет отличное стандартное свойство — ВместеСоСледующим. Оно указывает системе, что текущая строка (или область строк) не должна оставаться "одинокой" внизу страницы, и ее необходимо переносить на следующий лист вместе с последующей областью.
Рассмотрим по шагам, как применить этот метод:
Строка). Если вы хотите применить это программно, то свойство задается для конкретной выводимой области.ВместеСоСледующим = Истина).Посмотрим на пример программной установки этого свойства при выводе строки таблицы:
// Получаем область строки из макета
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
// Устанавливаем свойство, чтобы связать ее со следующей выводимой областью
ОбластьСтрока.Область().ВместеСоСледующим = Истина;
Как это работает на практике: Когда платформа пытается вывести последнюю строку таблицы, она проверяет, поместится ли эта строка вместе с идущим следом подвалом на текущей странице. Если подвал большой и не влезает на текущий лист, платформа автоматически перенесет последнюю строку таблицы вместе с подвалом на новую страницу. На последней странице у вас распечатается шапка таблицы, под ней будет находиться ровно одна строка данных, а далее — подвал. Это полностью решает проблему "пустой" шапки.
Минусы метода: Если подвал документа чрезвычайно огромный (например, занимает более половины страницы), перенос даже одной строки вместе с ним может не спасти ситуацию — они все равно могут не поместиться вдвоем на новый лист. Кроме того, на предпоследней странице может образоваться избыточное пустое пространство.
Если вам требуется более точный контроль процесса, мы можем использовать программный метод проверки вывода областей с помощью ПроверитьВывод(). Разберем алгоритм решения, который предложил автор исходной темы на форуме.
Суть метода заключается в том, чтобы на последней итерации цикла вывода строк проверить, поместится ли подвал документа на текущую страницу. Если подвал не помещается, мы принудительно переносим последнюю строку таблицы на следующий лист с помощью явного добавления разделителя страниц.
Проанализируем пример кода, реализующий этот подход:
// Количество строк в исходной табличной части
ВсегоСтрок = Товары.Количество();
Для i = 1 По ВсегоСтрок Цикл
// Получаем и заполняем область строки
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
ЗаполнитьЗначенияСвойств(ОбластьСтрока.Параметры, Товары[i - 1]);
// Особое условие для последней строки таблицы
Если i = ВсегоСтрок Тогда
// Проверяем, поместится ли область подвала на текущую страницу
Если Не ТабДок.ПроверитьВывод(ОбластьПодвал) Тогда
// Если подвал не влезает, принудительно переносим последнюю строку на новую страницу
ТабДок.ВывестиГоризонтальныйРазделительСтраниц();
КонецЕсли;
КонецЕсли;
// Выводим строку в табличный документ
ТабДок.Вывести(ОбластьСтрока);
КонецЦикла;
// В конце спокойно выводим подвал
ТабДок.Вывести(ОбластьПодвал);
Благодаря этому нехитрому условию, на последней странице гарантированно останется как минимум одна строка таблицы под автоматически продублированной шапкой.
В сложных коммерческих тиражируемых решениях (например, в типовых конфигурациях на базе БСП при формировании ТОРГ-12 или УПД) разработчики часто полностью отказываются от стандартного механизма ПовторятьПриПечатиСтроки. Вместо этого они реализуют полный программный контроль вывода шапки и подвала.
Давайте разберем по шагам, как построить такой алгоритм:
Строка таблицы + Шапка таблицы. Зачем? Чтобы в случае перехода на новую страницу гарантировать место под шапку.Строка таблицы + Шапка таблицы + Подвал.Посмотрим на практическую реализацию этого надежного подхода:
ТабДок = Новый ТабличныйДокумент;
ТабДок.ИмяПараметровПечати = "ПАРАМЕТРЫ_ПЕЧАТИ_НАША_ФОРМА";
ОбластьШапкаДокумента = Макет.ПолучитьОбласть("Шапка");
ОбластьШапкаТаблицы = Макет.ПолучитьОбласть("ШапкаТаблицы");
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
ОбластьПодвал = Макет.ПолучитьОбласть("Подвал");
// Начальный вывод
ТабДок.Вывести(ОбластьШапкаДокумента);
ТабДок.Вывести(ОбластьШапкаТаблицы);
ВсегоСтрок = СписокТоваров.Количество();
Для Индекс = 0 По ВсегоСтрок - 1 Цикл
СтрокаДанных = СписокТоваров[Индекс];
ЗаполнитьЗначенияСвойств(ОбластьСтрока.Параметры, СтрокаДанных);
// Создаем массив для проверки вывода
МассивПроверки = Новый Массив;
МассивПроверки.Добавить(ОбластьСтрока);
// Если это последняя строка, обязательно добавляем в проверку подвал
Если Индекс = ВсегоСтрок - 1 Тогда
МассивПроверки.Добавить(ОбластьПодвал);
КонецЕсли;
// Проверяем вывод накопленного пакета областей
Если Не ТабДок.ПроверитьВывод(МассивПроверки) Тогда
// Если не влезает, переносим страницу и вручную дублируем шапку таблицы
ТабДок.ВывестиГоризонтальныйРазделительСтраниц();
ТабДок.Вывести(ОбластьШапкаТаблицы);
КонецЕсли;
ТабДок.Вывести(ОбластьСтрока);
КонецЦикла;
// Финальный вывод подвала
Если Не ТабДок.ПроверитьВывод(ОбластьПодвал) Тогда
ТабДок.ВывестиГоризонтальныйРазделительСтраниц();
EndЕсли;
ТабДок.Вывести(ОбластьПодвал);
Этот метод является наиболее отказоустойчивым и гибким. Он на 100% гарантирует, что шапка таблицы никогда не появится на листе, где присутствуют только подписи или итоговая информация.
Разработчики часто жалуются, что метод ПроверитьВывод() возвращает некорректные результаты или ведет себя нестабильно на компьютерах разных пользователей. Выясним основные причины такого поведения и способы их устранения:
ПроверитьВывод() производит расчеты на основе физических параметров страницы (размер бумаги, поля, ориентация), установленных для принтера. Чтобы платформа понимала, какие именно настройки использовать, обязательно задавайте свойство ИмяПараметровПечати табличного документа до начала проверок. Например: ТабДок.ИмяПараметровПечати = "УникальноеИмяНастроекПечати";.ПроверитьВывод() может всегда возвращать значение Истина или работать некорректно.АвтоМасштаб, ОриентацияСтраницы, Поля (верхнее, нижнее, левое, правое).Применяя данные подходы, вы сможете создавать профессиональные печатные формы, которые будут корректно выводиться на печать у любых пользователей вне зависимости от объема выводимых данных!