При разработке печатных форм документов часто возникает задача условного вывода отдельных строк. Типичный сценарий — печать группового приказа (например, кадрового перемещения списком сотрудников), где для каждого человека формируется отдельная страница, но состав строк должен гибко меняться в зависимости от условий.
Рассмотрим ситуацию, с которой сталкиваются разработчики: попытка скрыть или удалить строку с фиксированным номером (например, строку 24) стандартным методом УдалитьОбласть() напрямую в макете приводит к искажению данных для всех последующих страниц. Проанализируем причины этой ошибки и разберем правильные способы реализации задачи.
Главная ошибка при модификации макета: объект Макет, полученный через ПолучитьМакет(), загружается в оперативную память. Если применить к нему метод Макет.УдалитьОбласть(...), структура макета изменится физически на весь сеанс формирования. На первой итерации цикла строка удалится, а на второй и последующих — макет уже окажется урезанным, что сместит все последующие координаты строк.
Наиболее надежный и архитектурно правильный путь — отказаться от попыток вырезать строки из готового листа и перестроить сам макет. Разделим печатную форму на именованные горизонтальные секции (области), после чего будем программно управлять их выводом в цикле.
Разберем реализацию по шагам:
ШапкаСотрудника).ДополнительнаяСтрока.ПодвалСотрудника.
ТабДок = Новый ТабличныйДокумент;
Макет = ПолучитьМакет("Макет");
ОбластьШапка = Макет.ПолучитьОбласть("ШапкаСотрудника");
ОбластьДоп = Макет.ПолучитьОбласть("ДополнительнаяСтрока");
ОбластьПодвал = Макет.ПолучитьОбласть("ПодвалСотрудника");
ПервыйСотрудник = Истина;
Для Каждого СтрСотрудник Из СписокСотрудников Цикл
Если Не ПервыйСотрудник Тогда
ТабДок.ВывестиГоризонтальныйРазделительСтраниц();
КонецЕсли;
ПервыйСотрудник = Ложь;
// Заполняем и выводим верхнюю часть
ОбластьШапка.Параметры.Заполнить(СтрСотрудник);
ТабДок.Вывести(ОбластьШапка);
// Проверяем условие для вывода 24-й строки
Если СтрСотрудник.ВыводитьДопИнформацию Тогда
ОбластьДоп.Параметры.Заполнить(СтрСотрудник);
ТабДок.Вывести(ОбластьДоп);
КонецЕсли;
// Заполняем и выводим нижнюю часть
ОбластьПодвал.Параметры.Заполнить(СтрСотрудник);
ТабДок.Вывести(ОбластьПодвал);
КонецЦикла;
Если макет представляет собой сложную типовую печатную форму, которую нежелательно перекраивать на мелкие секции, применим метод изолированного формирования. Для каждого сотрудника создадим отдельный временный табличный документ, где номер строки всегда будет оставаться фиксированным.
Посмотрим на пример реализации:
ТабДок = Новый ТабличныйДокумент;
Макет = ПолучитьМакет("Макет");
ОбластьМакета = Макет.ПолучитьОбласть("ПечатнаяФорма");
Первый = Истина;
Для Каждого СтрСотрудник Из СписокСотрудников Цикл
Если Не Первый Тогда
ТабДок.ВывестиГоризонтальныйРазделительСтраниц();
КонецЕсли;
Первый = Ложь;
// Создаем отдельный документ для одной страницы
ВременныйТабДок = Новый ТабличныйДокумент;
ОбластьМакета.Параметры.Заполнить(СтрСотрудник);
ВременныйТабДок.Вывести(ОбластьМакета);
// В рамках ВременныйТабДок строка ВСЕГДА имеет номер 24
Если Не СтрСотрудник.ВыводитьДопИнформацию Тогда
ВременныйТабДок.Область("R24").Видимость = Ложь;
КонецЕсли;
// Добавляем готовую страницу в итоговый документ
ТабДок.Вывести(ВременныйТабДок);
КонецЦикла;
Если вывод производится последовательно в единый результирующий документ, номер целевой строки смещается с каждой новой страницей. Рассчитаем актуальный номер строки динамически, фиксируя высоту таблицы перед добавлением очередного блока.
Разберем этот алгоритм:
ТабДок = Новый ТабличныйДокумент;
Макет = ПолучитьМакет("Макет");
ОбластьМакета = Макет.ПолучитьОбласть("ПечатнаяФорма");
Для Каждого СтрСотрудник Из СписокСотрудников Цикл
// Фиксируем количество строк до вывода новой страницы
ТекущееСмещение = ТабДок.ВысотаТаблицы;
ОбластьМакета.Параметры.Заполнить(СтрСотрудник);
ТабДок.Вывести(ОбластьМакета);
Если Не СтрСотрудник.ВыводитьДопИнформацию Тогда
// Вычисляем абсолютный номер строки в результирующем документе
НомерСтроки = ТекущееСмещение + 24;
ИмяОбласти = "R" + Формат(НомерСтроки, "ЧГ=0");
ТабДок.Область(ИмяОбласти).Видимость = Ложь;
КонецЕсли;
ТабДок.ВывестиГоризонтальныйРазделительСтраниц();
КонецЦикла;
Привязка к жестким номерам строк (например, «24») несет в себе риски: при любом обновлении макета или изменении типовой конфигурации позиция строки может сдвинуться. Чтобы сделать код устойчивым к изменениям, воспользуемся методом НайтиТекст().
Проанализируем пример поиска:
// Ищем ячейку с определенным текстом или служебным маркером
НайденнаяОбласть = ВременныйТабДок.НайтиТекст("Основание перевода:");
Если НайденнаяОбласть <> Неопределено Тогда
// Получаем номер строки через свойство Верх области
НомерСтроки = НайденнаяОбласть.Верх;
ВременныйТабДок.Область("R" + Формат(НомерСтроки, "ЧГ=0")).Видимость = Ложь;
КонецЕсли;
Рассмотрим разницу между тремя механизмами скрытия строк в результирующем документе:
Видимость = Ложь: наиболее чистый способ. Строка полностью исключается из отображения и печати, не сдвигая координаты других строк и не оставляя визуальных дефектов.УдалитьОбласть(..., ТипСмещенияТабличногоДокумента.ПоВертикали): физически вырезает ячейки и поднимает нижние строки вверх. Применяйте его осторожно: если требуется удалить несколько строк на одном листе, удаление необходимо выполнять строго снизу вверх (от больших номеров строк к меньшим), иначе последующие индексы сместятся.