При разработке отчетов в системе 1С:Предприятие 8.3 часто возникает задача создания сложных печатных форм, где количество колонок заранее неизвестно и зависит от данных (например, табель учета рабочего времени, график отпусков или календарь продаж). В таких случаях стандартного последовательного вывода строк недостаточно. Нам необходимо комбинировать горизонтальные и вертикальные области макета.
В этой статье мы подробно разберем, как программно управлять выводом областей, рассмотрим методы Вывести() и Присоединить(), а также изучим продвинутые техники работы с пересечениями областей и форматированием итогового документа.
Для начала уясним базовый принцип формирования табличного документа. Процесс можно представить как движение "каретки" или курсора по листу бумаги:
Вывести() — берет область из макета и размещает ее ниже уже выведенных данных. Каретка переходит на начало следующей строки.Присоединить() — берет область и размещает ее справа от последней выведенной области. Это ключевой инструмент для создания динамических колонок.Рассмотрим практическую реализацию на примере формирования графика, где строки — это сотрудники, а колонки — дни месяца.
Проанализируем ситуацию, когда нам нужно вывести шапку таблицы, а затем заполнить её динамическими колонками с датами. Представим, что у нас в макете созданы области Шапка, ШапкаТаблицы, День (вертикальная область для даты) и Строка (горизонтальная область для данных сотрудника).
Ниже приведена логика построения такого документа:
// Инициализируем табличный документ и получаем макет
ТабДок = Новый ТабличныйДокумент;
Макет = ПолучитьМакет("Макет");
// 1. Выводим статичную шапку (горизонтально)
Область = Макет.ПолучитьОбласть("Шапка");
Область.Параметры.НомерПриказа = СсылкаНаОбъект.НомерПриказа;
ТабДок.Вывести(Область);
// 2. Подготавливаем заголовок таблицы
Область = Макет.ПолучитьОбласть("ШапкаТаблицы");
ТабДок.Вывести(Область);
// 3. Формируем динамические колонки (дни месяца)
ОбластьДень = Макет.ПолучитьОбласть("День");
НачДата = СсылкаНаОбъект.ДатаНачала;
КонДата = СсылкаНаОбъект.ДатаОкончания;
ТекДата = НачДата;
Пока ТекДата <= КонДата Цикл
ОбластьДень.Параметры.НД = День(ТекДата);
// Присоединяем колонку справа к текущей строке
ТабДок.Присоединить(ОбластьДень);
ТекДата = ТекДата + 86400; // Переход к следующему дню
КонецЦикла;
В этом фрагменте мы видим, как после вывода основной шапки метод Присоединить() начинает "достраивать" таблицу вправо, создавая календарную сетку. Обратите внимание, что расчет дат и циклы позволяют сделать таблицу любой ширины в зависимости от выбранного периода.
Часто программисты пытаются вычислить адрес ячейки вручную, используя формат R1C1, например: ТабДок.Область("R7C" + НомерКолонки). Однако в 1С существует гораздо более изящный и надежный способ — работа с пересечениями именованных областей.
Если в вашем макете определена горизонтальная область (строки) с именем СтрокаДанных и вертикальная область (колонки) с именем КолонкаДня, вы можете получить доступ к ячейке на их пересечении одной строкой кода:
// Получаем область на пересечении
ОбластьЯчейка = Макет.ПолучитьОбласть("СтрокаДанных|КолонкаДня");
// Заполняем параметры ячейки
ОбластьЯчейка.Параметры.Значение = "Явка";
// Выводим или присоединяем
ТабДок.Присоединить(ОбластьЯчейка);
Этот метод позволяет избежать ошибок при изменении структуры макета. Даже если вы добавите новую строку в макет, 1С сама определит новые координаты пересечения по именам.
При создании широких таблиц с большим количеством вертикальных областей (дней, месяцев) крайне важно обеспечить удобство пользователя. Рассмотрим основные приемы улучшения юзабилити:
ФиксацияСверху и ФиксацияСлева.
Например: ТабДок.ФиксацияСлева = 4; закрепит первые четыре колонки.
Присоединить() колонки могут "схлопываться". Проверьте свойство ШиринаКолонки в макете или установите ТабДок.АвтоМасштаб = Истина; для автоматического подгона под размер страницы.Используйте ТабДок.НачатьГруппировкуКолонок(); перед циклом вывода дней месяца и ТабДок.ЗакончитьГруппировкуКолонок(); после завершения месяца. Это создаст удобные "плюсики" для сворачивания периодов.
Обобщим алгоритм действий для построения полноценного отчета с пересекающимися областями:
Вывести().Присоединить() для вертикальных областей заголовков.Вывести() для левой части строки (ФИО, Табельный номер).Присоединить() для вывода данных на пересечении (явки, часы).Пример реализации вложенного цикла:
Для Каждого ТекущийСотрудник Из СписокСотрудников Цикл
// Выводим начало строки (горизонтальная область)
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
ОбластьСтрока.Параметры.ФИО = ТекущийСотрудник.Наименование;
ТабДок.Вывести(ОбластьСтрока);
// Присоединяем данные по дням (вертикальная область)
Для Каждого ТекДень Из МассивДней Цикл
ОбластьДанные = Макет.ПолучитьОбласть("Строка|КолонкаДня");
ОбластьДанные.Параметры.Часы = ТекущийСотрудник.ПолучитьЧасы(ТекДень);
ТабДок.Присоединить(ОбластьДанные);
КонецЦикла;
КонецЦикла;
Важный момент: при вызове ТабДок.Вывести(ОбластьСтрока) система понимает, что нужно начать новую строку. Все последующие вызовы Присоединить() будут добавлять ячейки именно в эту новую строку, пока снова не будет вызван метод Вывести().
Используя эти методы, мы можем создавать отчеты любой сложности, обеспечивая высокую скорость работы и гибкость настройки печатных форм под требования бизнеса.