Как сохранить произвольную иерархию в СКД при добавлении вышестоящей группировки?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке отчетов в системе компоновки данных (СКД) нередко возникает задача построить иерархическое дерево по произвольному реквизиту. Типичный пример — документ Задача с реквизитом РодительскаяЗадача. Для выстраивания такого дерева используется связь набора данных с самим собой по ключам подчинения. Однако как только мы добавляем в структуру отчета вышестоящую группировку (например, по проекту, автору или подразделению), иерархия задач ломается и превращается в плоский список. Разберем, почему это происходит и как правильно решить данную проблему.

Выясним причину: почему иерархия схлопывается в плоский список?

Проанализируем механику работы СКД. Рекурсивное построение иерархии через связи наборов данных базируется на последовательном обходе записей: платформа берет начальные элементы (корень иерархии, где родитель пуст) и для каждого из них ищет подчиненные строки.

Когда мы добавляем вышестоящую группировку, поведение компоновщика меняется:

  1. Разрыв контекста выборки: СКД пытается выстроить дерево задач строго внутри порции данных, отфильтрованной текущей группировкой. Если значение вышестоящего реквизита у дочерней задачи отличается от значения у родительской (или у родительской задачи реквизит не заполнен), родитель отсекается. Платформа не может связать элемент с его предком и выводит дочерний элемент на верхнем уровне группы в виде плоского списка.
  2. Недостижимость корня иерархии: В настройках связи наборов данных для произвольной иерархии указывается условие начального значения (как правило, незаполненный родитель). Если элемент с пустым родителем не попадает в текущее значение вышестоящей группировки, рекурсия прерывается у самого основания.
  3. Потеря фильтра в связях: Если рекурсивная связь набора данных настроена только по ключам подчинения (например, Ссылка = РодительскаяЗадача), СКД теряет контекст вышестоящего поля при переходе на следующий уровень дерева.

Способ 1. Добавление поля группировки в условия связи наборов данных

Рассмотрим самое простое исправление ситуации, когда реквизит вышестоящей группировки совпадает у родителя и всех его потомков. По умолчанию связь набора с самим собой содержит только ключевые поля иерархии. Нам необходимо принудительно связать уровни еще и по реквизиту группировки.

Разберем по шагам настройку на вкладке Связи наборов данных:

  1. Оставляем стандартную рекурсивную связь: Источник связи — наш набор, Приемник связи — тот же набор, Выражение источник — Ссылка, Выражение приемник — РодительскаяЗадача, Начальное значение связи — ЗначениеЗаполнено(РодительскаяЗадача) = Ложь.
  2. Добавляем вторую строку связи между этим же набором данных:
    • Источник связи: наш набор;
    • Приемник связи: тот же набор;
    • Выражение источник: ПолеВышестоящейГруппировки;
    • Выражение приемник: ПолеВышестоящейГруппировки.

Благодаря этому СКД при поиске потомков передает значение вышестоящей группировки как контекстный фильтр и не теряет структуру ветки.

Способ 2. Наследование значения группировки от корня иерархии в запросе

Часто встречается ситуация, когда подчиненные задачи имеют незаполненное или отличающееся значение вышестоящего реквизита, но логически вся ветка должна подчиняться значению корневой задачи. В этом случае группировка должна выполняться не по собственному реквизиту текущей задачи, а по значению корня.

Посмотрим на пример запроса, где мы разузловываем цепочку родителей для получения корневого значения реквизита Проект:


ВЫБРАТЬ
    Задача.Ссылка КАК Задача,
    Задача.РодительскаяЗадача КАК РодительскаяЗадача,
    ЕСТЬNULL(Родитель2.Проект, ЕСТЬNULL(Родитель1.Проект, Задача.Проект)) КАК ПроектДляГруппировки
ИЗ
    Документ.Задача КАК Задача
    ЛЕВОЕ СОЕДИНЕНИЕ Документ.Задача КАК Родитель1
        ПО Задача.РодительскаяЗадача = Родитель1.Ссылка
    ЛЕВОЕ СОЕДИНЕНИЕ Документ.Задача КАК Родитель2
        ПО Родитель1.РодительскаяЗадача = Родитель2.Ссылка

Используя вычисленное поле ПроектДляГруппировки в вышестоящей группировке, мы гарантируем, что вся ветка от корня до крайних листьев попадет в один и тот же блок отчета, и иерархия задач не распадется.

Способ 3. Использование вложенной схемы компоновки данных

Если требуется полностью изолировать иерархию задач от влияния вышестоящей структуры, рассмотрим архитектурное решение через вложенную схему (вложенный отчет). Это исключает пересечение контекстов группировок.

Разберем алгоритм настройки:

  1. В основной схеме компоновки данных получаем список записей только для вышестоящей группировки (например, список проектов).
  2. Во вложенную схему выносим выборку задач и настраиваем там рекурсивную произвольную иерархию по реквизиту РодительскаяЗадача.
  3. Во вложенной схеме создаем параметр отбора (например, ПроектЗадач).
  4. В основной схеме на вкладке Настройки в структуру добавляем элемент Вложенный отчет внутрь группировки по проекту.
  5. На вкладке Вложенные схемы связываем поле текущей группировки основной схемы с параметром вложенной схемы.

При таком подходе иерархия задач внутри каждой группы формируется абсолютно независимо, что исключает появление плоского списка.

← На главную