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