Как вывести уровни иерархии справочника в отдельные колонки строки в СКД?

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

При разработке отчетов на базе Системы компоновки данных (СКД) в 1С программисты часто сталкиваются со стандартным поведением системы при выводе иерархических справочников (например, Номенклатура или Подразделения). По умолчанию СКД выводит иерархию в виде дерева («лесенкой» вниз). Это удобно для визуального восприятия на экране, но абсолютно непригодно, если пользователю нужно выгрузить данные в Excel для последующего анализа, построить плоскую таблицу или вывести каждый уровень в отдельную колонку (например: Склад | Папка 1-го уровня | Папка 2-го уровня | Товар).

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

Вариант 1. Использование функции ВычислитьВыражение с контекстом "Иерархия"

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

Разберем по шагам, как настроить этот механизм:

  1. Перейдем на вкладку Вычисляемые поля в схеме компоновки данных.
  2. Добавим новое поле, например, Родитель1Уровня.
  3. В колонке Выражение напишем следующую конструкцию:
    
    Выбор 
        Когда Уровень() > 0 
            Тогда ВычислитьВыражение("Ссылка", , "Иерархия") 
        Иначе Неопределено 
    Конец
    

Параметр "Иерархия" указывает СКД, что вычисление выражения должно происходить исключительно в контексте родительских записей текущей группировки. Это позволяет системе «подниматься» по дереву элементов вверх и возвращать значения вышестоящих уровней непосредственно в строку детальной записи элемента. Этот способ наиболее элегантен, так как не требует изменения текста запроса.

Вариант 2. Выравнивание уровней через функцию Уровень() в вычисляемых полях

Часто разработчики пытаются решить задачу «в лоб», предлагая пользователям выбирать поля через точку: Номенклатура.Родитель, Номенклатура.Родитель.Родитель и так далее. Однако этот подход имеет серьезный недостаток. Если у вас в справочнике есть товары с разной глубиной вложенности (один лежит в папке 2-го уровня, а другой — в папке 4-го уровня), то поле Номенклатура.Родитель для них вернет папки совершенно разных уровней. В результате колонки в отчете будут заполнены хаотично.

Чтобы гарантировать, что в первой колонке всегда будет отображаться только корневая папка (1-й уровень), во второй — только подпапка (2-й уровень) и так далее, мы можем использовать выравнивание с помощью системной функции Уровень(). Рассмотрим пример настройки вычисляемых полей для справочника с максимальной вложенностью в 3 уровня:

  1. Создадим вычисляемое поле Родитель_1_Уровня со следующим выражением:
    
    Выбор 
        Когда Номенклатура.Уровень() = 1 Тогда Номенклатура.Родитель 
        Когда Номенклатура.Уровень() = 2 Тогда Номенклатура.Родитель.Родитель 
        Когда Номенклатура.Уровень() = 3 Тогда Номенклатура.Родитель.Родитель.Родитель 
        Иначе Неопределено 
    Конец
    
  2. Создадим вычисляемое поле Родитель_2_Уровня:
    
    Выбор 
        Когда Номенклатура.Уровень() = 2 Тогда Номенклатура.Родитель 
        Когда Номенклатура.Уровень() = 3 Тогда Номенклатура.Родитель.Родитель 
        Иначе Неопределено 
    Конец
    
  3. Создадим вычисляемое поле Родитель_3_Уровня:
    
    Выбор 
        Когда Номенклатура.Уровень() = 3 Тогда Номенклатура.Родитель 
        Иначе Неопределено 
    Конец
    

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

Вариант 3. Настройка структуры СКД с отбором по системному полю "Уровень"

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

Проанализируем алгоритм настройки:

  1. В наборе данных запроса добавим два одинаковых поля для номенклатуры. Одно назовем стандартно — Товар, а второму дадим псевдоним ТоварИерархия.
  2. Перейдем на вкладку Настройки. В структуре отчета создадим группировку по полю ТоварИерархия. В свойствах этой группировки укажем тип группировки: Только иерархия (это заставит СКД выводить исключительно родительские папки).
  3. В настройках этой конкретной группировки перейдем на вкладку Отбор и добавим условие: СистемныеПоля.Уровень = 1. Очень важно в свойствах элемента отбора указать параметр Применять: Только для иерархии. Это ограничит вывод только самым верхним уровнем папок.
  4. В свойствах этой же группировки найдем параметр Расположение группировок и установим его в значение Нет. Это скроет стандартный «сдвиг» строк и предотвратит образование лесенки.
  5. Внутрь созданной группировки добавим подчиненную группировку по детальным записям (или по полю Товар). В выбранные поля отчета вынесем одновременно и ТоварИерархия, и Товар.

В результате СКД сопоставит родителя верхнего уровня и конечный товар в рамках одной строки, выведя их в разные колонки.

Вариант 4. Использование связей наборов данных (Рекурсивный обход)

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

Выполним следующие шаги для настройки связей:

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

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

Резюме и рекомендации

Мы рассмотрели четыре принципиально разных подхода к решению задачи вывода иерархии в строку:

← На главную