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

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

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

В данной статье мы разберем наиболее эффективные методы решения этой задачи: от использования пользовательских полей с логическими условиями до применения вычисляемых полей.

Метод 1. Использование пользовательских полей с логикой выбора уровня

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

Для реализации этого метода перейдем на вкладку Пользовательские поля в схеме СКД и создадим три поля выражения.

Поле «Уровень 1»

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

Используем следующее выражение для поля ПервыйУровень, которое можно предварительно отладить через консоль запросов:


Выбор 
    Когда [Подразделение.Вышестоящее подразделение.Вышестоящее подразделение] <> Значение(Справочник.ПодразделенияОрганизаций.ПустаяСсылка) 
        Тогда [Подразделение.Вышестоящее подразделение.Вышестоящее подразделение] 
    Иначе Выбор 
        Когда [Подразделение.Вышестоящее подразделение] <> Значение(Справочник.ПодразделенияОрганизаций.ПустаяСсылка) 
            Тогда [Подразделение.Вышестоящее подразделение] 
        Иначе Подразделение 
    Конец 
Конец

Поле «Уровень 2»

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


Выбор 
    Когда [Подразделение.Вышестоящее подразделение.Вышестоящее подразделение] <> Значение(Справочник.ПодразделенияОрганизаций.ПустаяСсылка) 
        Тогда [Подразделение.Вышестоящее подразделение] 
    Иначе Выбор 
        Когда [Подразделение.Вышестоящее подразделение] <> Значение(Справочник.ПодразделенияОрганизаций.ПустаяСсылка) 
            Тогда Подразделение 
        Иначе Значение(Справочник.ПодразделенияОрганизаций.ПустаяСсылка) 
    Конец 
Конец

Поле «Уровень 3»

Третий уровень заполняется только тогда, когда подразделение сотрудника является самым глубоким в нашей трехзвенной структуре.


Выбор 
    Когда [Подразделение.Вышестоящее подразделение.Вышестоящее подразделение] <> Значение(Справочник.ПодразделенияОрганизаций.ПустаяСсылка) 
        Тогда Подразделение 
    Иначе Значение(Справочник.ПодразделенияОрганизаций.ПустаяСсылка) 
Конец

После создания этих полей необходимо зайти в настройки отчета и добавить их в Выбранные поля вместо стандартного поля Подразделение. Группировку при этом следует оставить линейной (без иерархии), чтобы данные выводились в одну строку по сотруднику.

Метод 2. Вычисляемые поля и функции общего модуля

Если структура компании динамична и уровней может быть больше трех, использование конструкций ВЫБОР КОГДА становится крайне неудобным. В таких случаях профессиональнее использовать Вычисляемые поля с вызовом функции из общего модуля 1С.

Рассмотрим пошагово этот процесс:

  1. Создадим в конфигурации общий модуль (например, ОбслуживаниеОтчетовСервер) с включенными флажками «Сервер» и «Внешнее соединение».
  2. Напишем функцию, которая возвращает родителя нужного уровня (в создании каркаса кода может помочь ИИ-помощник).

Функция ПолучитьРодителяУровня(ПодразделениеСсылка, НужныйУровень) Экспорт
    Если ПодразделениеСсылка.Пустая() Тогда
        Возврат Справочники.ПодразделенияОрганизаций.ПустаяСсылка();
    КонецЕсли;
    
    ТекущийОбъект = ПодразделениеСсылка;
    МассивРодителей = Новый Массив;
    
    // Собираем цепочку родителей снизу вверх
    Пока ЗначениеЗаполнено(ТекущийОбъект.Родитель) Цикл
        МассивРодителей.Вставить(0, ТекущийОбъект.Родитель);
        ТекущийОбъект = ТекущийОбъект.Родитель;
    КонецЦикла;
    
    // Добавляем само подразделение в конец цепочки
    МассивРодителей.Добавить(ПодразделениеСсылка);
    
    // Проверяем, существует ли запрашиваемый уровень
    Если НужныйУровень <= МассивРодителей.Количество() Тогда
        Возврат МассивРодителей[НужныйУровень - 1];
    Иначе
        Возврат Справочники.ПодразделенияОрганизаций.ПустаяСсылка();
    КонецЕсли;
КонецФункции

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

ОбслуживаниеОтчетовСервер.ПолучитьРодителяУровня(Подразделение, 1)

ОбслуживаниеОтчетовСервер.ПолучитьРодителяУровня(Подразделение, 2)

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

Метод 3. Настройка расположения группировок

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

Там есть параметр Расположение полей группировок. По умолчанию он установлен в значение «Вместе», что заставляет СКД выводить всю иерархию в одну колонку. Если установить значение Отдельно, каждое поле группировки будет выведено в своей колонке.

Чтобы этот метод сработал для линейного вывода подразделений в строку, проделаем следующее:

  1. В структуре настроек добавим группировку по полю Подразделение.Родитель.Родитель (для 1-го уровня).
  2. Внутри нее добавим группировку по Подразделение.Родитель (для 2-го уровня).
  3. В самом низу — группировку по полю Подразделение.
  4. Для каждой группировки в выбранных полях укажем только соответствующее поле.

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

Типичные ошибки при настройке

Разберем ситуацию, когда при использовании первого метода (пользовательские поля) данные «смещаются» или не отображаются. Это часто происходит, если не учитывается проверка на ПустуюСсылку. Проанализируем: если мы просто обратимся к Подразделение.Родитель.Родитель, а у подразделения всего один уровень вложенности, СКД может вернуть NULL или пустую ссылку в первой колонке, хотя там должно быть название самого подразделения. Именно поэтому в выражениях ВЫБОР КОГДА важно начинать проверку с самого глубокого уровня вложенности или использовать функции, корректно обходящие дерево сверху вниз.

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

← На главную