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