При разработке печатных форм в системе 1С:Предприятие программисты часто сталкиваются с необходимостью вывести сложный «подвал» документа. Трудности возникают, когда внутри подвала должна находиться динамическая часть — например, список курсов валют, использованных в документе, или перечень налогов. Попытка создать «секцию внутри секции» в макете и вывести её стандартными методами часто приводит к дублированию строк или некорректному заполнению параметров. Проанализируем, как решить эту задачу эффективно и правильно.
Рассмотрим ситуацию, с которой часто сталкиваются начинающие разработчики. В макете создается область Подвал, а внутри неё — область Курс. Код вывода выглядит примерно так:
ОбластьПодвал = Макет.ПолучитьОбласть("Подвал");
ОбластьПодвал.Параметры.ПолныйИтог = СуммаИтого;
ОбластьПодвалКурс = Макет.ПолучитьОбласть("Курс");
Для Каждого Стр Из ТаблицаКурсов Цикл
ОбластьПодвал.Параметры.Валюта = Стр.Валюта;
ТабДок.Вывести(ОбластьПодвалКурс);
КонецЦикла;
ТабДок.Вывести(ОбластьПодвал);
В данном примере заложены сразу две фундаментальные ошибки. Во-первых, при выполнении метода Макет.ПолучитьОбласть("Подвал") система копирует в память всю область «Подвал» целиком, включая те строки, которые визуально в макете относятся к секции «Курс». Во-вторых, разработчик пытается заполнить параметры в объекте ОбластьПодвал, а выводит объект ОбластьПодвалКурс. Нужно помнить: каждый вызов ПолучитьОбласть создает новый, независимый объект. Параметры, установленные в одной области, никогда не появятся в другой автоматически.
Это самый надежный и простой в поддержке метод. Вместо того чтобы пытаться вкладывать области друг в друга в редакторе макета, мы разделим подвал на три логические части, идущие друг за другом по вертикали:
Разберем по шагам алгоритм вывода при таком подходе:
// 1. Выводим верхнюю часть подвала
ОбластьНачало = Макет.ПолучитьОбласть("Подвал_Начало");
ОбластьНачало.Параметры.ИтоговаяСумма = ИтогДокумента;
ТабДок.Вывести(ОбластьНачало);
// 2. Выводим динамические строки в цикле
ОбластьСтрока = Макет.ПолучитьОбласть("Подвал_СтрокаКурса");
Для Каждого СтрокаКурса Из ТЗ_Курсов Цикл
ОбластьСтрока.Параметры.Заполнить(СтрокаКурса); // Автоматическое заполнение параметров
ТабДок.Вывести(ОбластьСтрока);
КонецЦикла;
// 3. Выводим финальную часть
ОбластьКонец = Макет.ПолучитьОбласть("Подвал_Конец");
ТабДок.Вывести(ОбластьКонец);
Этот метод исключает путаницу с «вложенностью» и позволяет легко менять структуру подвала, не ломая логику кода. При разработке можно опереться на пример внешней печатной формы с выводом подписей и печатей на базе БСП.
Если вам все же необходимо использовать структуру «секция в секции» (например, для визуального удобства в макете), следует применять механизм пересечения областей. В 1С к области можно обратиться через синтаксис "ИмяСтроки|ИмяКолонки" или "ОсновнаяОбласть|ВложеннаяОбласть".
Выясним причину, почему это работает. Когда вы именуете строки макета, вы можете задать имя для группы строк (например, Подвал с 10 по 20 строку) и внутри неё задать имя для одной строки (например, Курс — 15 строка). Чтобы получить именно строку курса как часть подвала, используйте код:
ОбластьКурса = Макет.ПолучитьОбласть("Подвал|Курс");
Однако будьте осторожны: если вы сначала выведете Подвал, а потом начнете выводить Курс, строки будут дублироваться, так как Курс уже входит в состав Подвала. В этом случае Подвал тоже нужно делить на подсекции, как описано в первом способе, но обращаться к ним через «вертикальную черту».
Чтобы не писать десятки строк кода для присвоения каждого параметра вручную, проанализируем возможности метода Заполнить(). Если имена параметров в ячейках макета совпадают с именами колонок вашей Таблицы Значений или именами реквизитов документа, можно использовать одну команду:
// Вместо:
// Область.Параметры.Курс = СтрокаДанных.Курс;
// Область.Параметры.Валюта = СтрокаДанных.Валюта;
// Используем:
Область.Параметры.Заполнить(СтрокаДанных);
Это делает код чище и значительно ускоряет разработку печатных форм со множеством полей.
При выводе динамических секций (таких как список курсов) в подвале документа возникает риск, что подвал «разорвется»: часть итогов останется на одной странице, а подписи переедут на другую. Это считается плохим тоном в оформлении документов. Рассмотрим, как этого избежать.
Перед выводом всех частей подвала мы должны собрать их в массив и проверить, помещаются ли они на оставшееся место текущего листа:
МассивОбластей = Новый Массив;
МассивОбластей.Добавить(ОбластьНачало);
// Добавляем в массив столько строк курса, сколько реально будет выведено
Для Каждого Стр Из ТЗ_Курсов Цикл
МассивОбластей.Добавить(ОбластьСтрока);
КонецЦикла;
МассивОбластей.Добавить(ОбластьКонец);
// Проверяем, поместится ли весь этот «пакет» областей
Если Не ТабДок.ПроверитьВывод(МассивОбластей) Тогда
ТабДок.ВывестиГоризонтальныйРазделительСтраниц();
КонецЕсли;
// Теперь можно спокойно выводить области одну за другой
Иногда подсекция «Курс» должна выводиться не строго под итогами, а, например, справа от блока с комментариями. В этом случае метод Вывести() не подойдет, так как он всегда переносит печать на новую строку. Посмотрим на работу метода Присоединить():
Вывести().Присоединить().Важно: для корректной работы Присоединить() области в макете должны быть разделены не только горизонтальными, но и вертикальными именованными областями (колонками). Для практической реализации такого вывода подойдёт готовый пример печати макета в несколько колонок.
Резюмируем: наиболее эффективный способ вывода вложенных секций — это линейное разделение макета на несколько последовательных областей. Это избавляет от проблем с адресацией параметров и обеспечивает гибкость при динамическом формировании строк. Не забывайте использовать ПроверитьВывод() для сохранения целостности документа при печати.