При разработке отчетов в системе компоновки данных (СКД) часто возникает задача вывести данные в виде иерархии, которая не совпадает с предопределенной иерархией справочника. Типичный пример — отчет по составу комплектов номенклатуры, где комплекты могут быть вложены друг в друга на любую глубину, а остатки хранятся в разрезе конечных элементов. В процессе решения этой задачи разработчики часто сталкиваются с двумя крайностями: либо в отчете появляются дубли строк, либо иерархия вовсе «схлопывается» в плоскую таблицу. Разберем по шагам, как правильно реализовать такую структуру.
Когда мы пытаемся построить иерархию по ссылочным полям (например, Номенклатура и Родитель в табличной части состава), СКД ориентируется на уникальность ссылок. Если один и тот же комплект (например, «Секция левая») входит в состав нескольких разных изделий, система при построении дерева может вывести его несколько раз. Это происходит потому, что в классической древовидной структуре справочника 1С один элемент не может иметь двух родителей. Пытаясь обойти это ограничение в СКД через связи наборов данных по ссылкам, мы получаем ситуацию, когда итоги начинают двоиться, а визуальная структура становится непредсказуемой.
Для корректного отображения одной и той же позиции в разных ветках иерархии нам необходимо сделать каждую ветку уникальной. Проанализируем способ создания синтетических ключей. Идея заключается в конкатенации кодов или идентификаторов всех родителей, ведущих к данному элементу.
Например, если у нас есть путь: Шкаф (001) -> Секция (005) -> Полка (009), то:
001/005/009001/005При таком подходе каждый узел в дереве отчета становится уникальным объектом, даже если ссылочно это одна и та же номенклатура. Это полностью исключает проблему дублирования при суммировании ресурсов.
Выясним причину распространенной ошибки: вы сформировали составные ключи, настроили связь набора данных «сам на себя», но вместо дерева получили обычный список. Рассмотрим два критических условия, без которых СКД не построит дерево:
001/005/009) и её родителем «Секцией» (ключ 001/005), в итоговой таблице данных обязательно должна присутствовать строка, где КлючЭлемента равен 001/005. Если ваш запрос выбирает только «листья» (конечные товары), дерево не соберется. Вам нужно программно или запросом добавить в таблицу все промежуточные уровни комплектации.NULL, укажите это в колонке «Начальное значение связи».Проанализируем процесс настройки наборов данных. Предположим, вы подготовили таблицу значений ТЗ_Данные с полями КлючЭлемента, КлючРодителя, Номенклатура, Количество.
Перейдем на вкладку «Связи наборов данных» и добавим связь:
КлючЭлемента = КлючРодителяКлючЭлемента.Рассмотрим пример кода для формирования такой таблицы значений, если мы используем программную подготовку данных:
// Пример формирования структуры в ТЗ
Для Каждого СтрокаСостава Из ТаблицаКомплектации Цикл
НоваяСтрока = ТЗ_Данные.Добавить();
// Формируем уникальный ключ как путь: "КодРодителя/КодЭлемента"
НоваяСтрока.КлючЭлемента = СтрокаСостава.ПутьКРодителю + "/" + СтрокаСостава.КодЭлемента;
НоваяСтрока.КлючРодителя = СтрокаСостава.ПутьКРодителю;
НоваяСтрока.Номенклатура = СтрокаСостава.Номенклатура;
НоваяСтрока.Количество = СтрокаСостава.Остаток;
КонецЦикла;
Если версия платформы позволяет (8.3.20+), эффективнее использовать рекурсивные временные таблицы. Это позволит переложить логику построения «материализованного пути» на СУБД. Посмотрим на логику построения такого запроса:
ВЫБРАТЬ
ИсходныеДанные.Ссылка КАК Ссылка,
ИсходныеДанные.Родитель КАК Родитель,
ВЫРАЗИТЬ(ИсходныеДанные.Ссылка.Код КАК СТРОКА(100)) КАК Путь
ПОМЕСТИТЬ ВТ_Дерево
ИЗ
Справочник.Номенклатура КАК ИсходныеДанные
ГДЕ
ИсходныеДанные.Родитель = ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Номенклатура.Ссылка,
Номенклатура.Родитель,
ВТ_Дерево.Путь + "/" + Номенклатура.Код
ИЗ
Справочник.Номенклатура КАК Номенклатура
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_Дерево КАК ВТ_Дерево
ПО Номенклатура.Родитель = ВТ_Дерево.Ссылка
При построении произвольной иерархии важно правильно настроить ресурсы. Поскольку один и тот же физический товар может отображаться в разных ветках (как часть разных комплектов), стандартное суммирование «по всем уровням» может привести к логическим ошибкам в понимании общего остатка.
Рекомендуется:
Количество указывать только детальные записи или конкретную группировку по вашему составному ключу.Подведем итог: построение произвольной иерархии в СКД требует строгого контроля за тем, чтобы каждый дочерний элемент имел своего родителя в наборе данных, а связи строились по уникальным текстовым путям, а не по ссылкам справочника. Это гарантирует отсутствие дублей и корректное развертывание дерева в отчете.