Как настроить отбор в произвольной иерархии СКД с выводом всей ветки?

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

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

Почему стандартный отбор ломает произвольную иерархию

Проанализируем ситуацию: в типовом механизме СКД условия отбора накладываются на записи набора данных еще на этапе выборки. Если условию удовлетворяет дочерний элемент (лист дерева), но не удовлетворяет родительский узел, родитель исключается из итогового результата. В результате цепочка подчинения разрывается, и дочерняя запись либо «теряется», либо выводится в корень отчета без контекста подчинения.

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

Решение 1. Настройка штатного механизма «Проверка иерархии»

Рассмотрим основной способ решения задачи, заложенный разработчиками платформы «1С:Предприятие». Для того чтобы платформа понимала произвольную иерархическую структуру при отборах, используется связка дополнительного набора данных и параметра проверки.

  1. Создадим дополнительный набор данных для проверки: Добавим в схему компоновки данных второй набор данных типа «Запрос» (назовем его, например, НаборДанныхПроверкаИерархии). В нем описывается связь родительских и дочерних узлов с фильтрацией по специальному параметру:
    
    ВЫБРАТЬ
        ИерархияДанных.Ссылка КАК Ссылка,
        ИерархияДанных.Родитель КАК Родитель
    ИЗ
        РегистрСведений.ПользовательскаяИерархия КАК ИерархияДанных
    ГДЕ
        ИерархияДанных.Родитель В (&РодительПроверки)
    
  2. Свяжем набор проверки сам с собой: Перейдем на вкладку Связи наборов данных и настроим рекурсивную связь:
    1. В качестве Источника и Приемника указываем наш созданный набор: НаборДанныхПроверкаИерархии.
    2. В поле Выражение источника указываем поле текущего узла: Ссылка.
    3. В поле Выражение приемника указываем поле родителя: Родитель.
    4. В колонке Параметры обязательно прописываем имя параметра из запроса: РодительПроверки.
    5. Включаем признак Список параметров. Это позволит платформе рекурсивно разворачивать все дерево узлов вниз и вверх.
  3. Укажем проверку иерархии в основном наборе: Вернемся на закладку Наборы данных к нашему основному набору. В таблице полей найдем группировочное поле, по которому строится иерархия. В колонке Проверка иерархии выбираем из выпадающего списка созданный нами НаборДанныхПроверкаИерархии.

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

Решение 2. Управление применением отбора в настройках группировки

Разберем еще один вариант, когда требуется вывести родительские уровни ветки до подходящего элемента. Платформа предоставляет возможность регулировать область применения фильтра.

Если отбор задается не в корневых настройках отчета, а в свойствах конкретной строки группировки (на вкладке «Отбор» выбранной группировки), в колонках настройки отбора появляется поле Применение. Оно имеет три режима:

  1. Иерархия: условие применяется ко всем узлам дерева (и к группам, и к детальным записям). Если родитель не удовлетворяет условию, он отсекается.
  2. Без иерархии: условие фильтрации применяется исключительно к детальным элементам (конечным записям). При этом родительские узлы по всей цепочке наверх выводятся в отчет без проверки условия, что сохраняет визуальную структуру всей ветки.
  3. Только иерархия: проверка накладывается исключительно на папки и родительские группировки.

Решение 3. Использование вычисляемых полей и агрегации по иерархии

Посмотрим на ситуацию, когда признак соответствия условию может располагаться на любом уровне дерева (как у предка, так и у потомка), и требуется оставить всю вертикальную ветвь. Для этого можно использовать агрегацию через вычисляемые поля.

  1. Добавим вычисляемое поле, например, ПризнакПодходит со значением 1, если условие выполняется, и 0 в противном случае: ВЫБОР КОГДА Реквизит = &НужноеЗначение ТОГДА 1 ИНАЧЕ 0 КОНЕЦ
  2. На вкладке Ресурсы рассчитаем агрегатное поле с функцией Максимум(ПризнакПодходит).
  3. В настройках группировки воспользуемся функцией ВычислитьВыражение с областью расчета "Иерархия", чтобы «поднять» или «опустить» факт наличия совпадения по всей цепочке подчинения, и наложим отбор на итоговое агрегированное значение.

Ограничения и рекомендации при работе с произвольной иерархией

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

  1. Наборы данных «Объект»: Штатный механизм проверки иерархии корректно работает динамически только с набором данных типа Запрос, так как СКД довыбирает данные порциями через передачу параметров в условие ГДЕ. Если данные загружаются из внешней таблицы значений (набор данных Объект), древовидную связность и отбор веток необходимо подготавливать программно в коде до передачи в компоновщик.
  2. Зацикливание структуры: При произвольных связях критически важно контролировать отсутствие циклических ссылок (ситуаций, когда элемент является родителем самого себя через цепочку узлов). Наличие цикла в рекурсивных связях СКД приведет к зависанию отчета или переполнению стека вызовов.
← На главную