При работе с Системой компоновки данных (СКД) часто возникает задача построения иерархического отчета на основе данных, которые не являются стандартными справочниками с предопределенной иерархией. Например, когда данные приходят из сложного запроса, таблицы значений или регистра сведений, где связи Родитель — Элемент заданы явно. Рассмотрим, как правильно настроить систему, чтобы получить полноценное дерево, а не плоский список или дублирующиеся ветки.
Представим ситуацию: у нас есть набор данных (таблица), где указаны идентификаторы элементов и их родители. Разберем типичный пример структуры данных, который часто используется для тестирования таких механизмов:
ВЫБРАТЬ 0 КАК Родитель, 1 КАК Элемент
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 0, 2
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 0, 3
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 1, 11
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 1, 12
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 2, 21
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 2, 22
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 11, 111
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 11, 112
Если просто вывести эти данные в СКД, мы получим линейный список. Наша цель — получить вложенную структуру, где элемент 111 находится внутри 11, а 11 в свою очередь внутри 1. Основная сложность заключается в том, что СКД должна понять, какой элемент является "корнем", а какой — "потомком", и запустить рекурсивный механизм построения связей.
Для реализации иерархии нам необходимо настроить вкладку Связи наборов данных. Проанализируем, какие параметры критически важны для правильной работы алгоритма:
НаборДанных1).Элемент.Родитель.Рассмотрим подробнее Начальное выражение связи. Если мы оставим его пустым, СКД может попытаться построить дерево для каждой записи из таблицы, что приведет к дублированию. Если мы хотим начать с самых верхних элементов, мы пишем условие, определяющее корень. Например: Родитель = 0 или Родитель ЕСТЬ NULL (в зависимости от ваших данных).
Выясним причину распространенной ошибки, когда в дереве появляются дублирующиеся узлы (например, элемент 11 отображается и как корень, и как дочерний элемент). Проанализируем ситуацию:
Когда СКД строит иерархию, она выполняет итерационный процесс. Если в настройках группировки отчета выбрано поле Родитель с типом Иерархия, система берет все уникальные значения этого поля и строит дерево вниз. Если при этом в связях наборов данных не задано Начальное выражение связи, то каждый элемент, который встречается в колонке Элемент, система считает потенциальным корнем новой ветки.
Чтобы этого избежать, необходимо четко разделять иерархическую связь в настройках компоновщика и логику выборки данных. Рекомендуется создавать группировку не по полю Родитель, а по полю Элемент, устанавливая тип Иерархия только тогда, когда связи наборов данных настроены корректно.
Если нам нужно вывести результат не в табличный документ, а в объект ДеревоЗначений на форме (например, в обычной форме обработки), мы используем следующий алгоритм. Разберем по шагам код инициализации и вывода:
Процедура кнОбновитьНажатие(Элемент)
// Получаем схему из макета
СКД = ЭтотОбъект.ПолучитьМакет("Макет1");
Настройки = СКД.НастройкиПоУмолчанию;
// Инициализируем компоновщик макета для работы с коллекциями
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпановки = КомпоновщикМакета.Выполнить(СКД, Настройки, , , Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
// Инициализируем процессор компоновки
ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпановки);
// Подготавливаем Дерево Значений и процесс вывода
ПроцессВывода = Новый ПроцессВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ДЗ = Новый ДеревоЗначений;
ПроцессВывода.УстановитьОбъект(ДЗ);
// Выводим результат
ПроцессВывода.Вывести(ПроцессорКомпоновкиДанных);
// Отображаем данные на форме
ЭлементыФормы.ДЗ.СоздатьКолонки();
КонецПроцедуры
Важно помнить: чтобы иерархия корректно передалась в ДеревоЗначений, в настройках группировки СКД должно быть выбрано именно Иерархия. Если вы добавите группировку Детальные записи внутрь иерархической группировки, это может создать лишние вложенные уровни, которые визуально воспринимаются как ошибки вывода.
Рассмотрим более сложный случай: нам нужно строить дерево не от самого верха, а от определенного узла, выбранного пользователем. Для этого проанализируем использование параметров:
&КорневойУзел.Элемент = &КорневойУзел.Такой подход позволяет избежать циклических ссылок и значительно ускоряет работу отчета на больших объемах данных, так как система не перебирает всю таблицу в поисках корней.
Посмотрим на основные правила, которые помогут избежать ошибок при построении произвольной иерархии:
Элемент и Родитель. Они должны быть идентичны (например, оба Число или оба Строка).0 и NULL). Приведите их к одному виду перед передачей в СКД.Следуя этим шагам, мы получаем гибкий и мощный инструмент для визуализации древовидных структур любой сложности, независимо от того, хранятся ли они в базе данных 1С или формируются динамически в памяти приложения.