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