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