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