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