Как получить вышестоящее подразделение в иерархии 1С:Бухгалтерия 8.3

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

В процессе разработки в конфигурации «1С:Бухгалтерия предприятия 8.3» часто возникает задача получения не просто текущего подразделения сотрудника, а всей цепочки его подчиненности или самого верхнего (головного) подразделения. Это необходимо для корректного формирования управленческой отчетности, распределения затрат или настройки прав доступа. Рассмотрим подробнее, как реализовать получение вышестоящих уровней иерархии различными способами — от простых обращений к реквизитам до сложных запросов и методов оптимизации.

Метод 1. Использование стандартного реквизита «Родитель»

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

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


// Получаем родителя текущего подразделения
ВышестоящееПодразделение = ТекущееПодразделение.Родитель;

Если ЗначениеЗаполнено(ВышестоящееПодразделение) Тогда
    Сообщить("Вышестоящее подразделение: " + ВышестоящееПодразделение);
КонецЕсли;

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

Метод 2. Поиск «корня» (самого верхнего уровня) через цикл

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

  1. Присваиваем вспомогательной переменной значение текущего подразделения.
  2. В цикле проверяем, заполнен ли родитель у текущего элемента.
  3. Если родитель существует, перезаписываем переменную и идем выше.
  4. Цикл остановится, когда мы дойдем до элемента, у которого родитель — пустая ссылка.

НужноеПодразделение = ТекущееПодразделение;

Пока ЗначениеЗаполнено(НужноеПодразделение.Родитель) Цикл
    НужноеПодразделение = НужноеПодразделение.Родитель;
КонецЦикла;

// В переменной НужноеПодразделение теперь самый верхний узел
Сообщить("Головное подразделение: " + НужноеПодразделение);

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

Метод 3. Получение всех уровней иерархии через запрос

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

Рассмотрим пример запроса:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ПодразделенияОрганизаций.Ссылка КАК Ссылка
    |ИЗ
    |	Справочник.ПодразделенияОрганизаций КАК ПодразделенияОрганизаций
    |ГДЕ
    |	ПодразделенияОрганизаций.Ссылка = &Ссылка
    |ИТОГИ ПО
    |	Ссылка ТОЛЬКО ИЕРАРХИЯ";

Запрос.УстановитьПараметр("Ссылка", ТекущееПодразделение);

РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией);

Пока Выборка.Следующий() Цикл
    // Здесь мы получим все уровни, начиная с верхнего
    Сообщить(Выборка.Ссылка);
КонецЦикла;

Использование ОБХОД РЕЗУЛЬТАТА ЗАПРОСА ПО ГРУППИРОВКАМ С ИЕРАРХИЕЙ позволяет нам удобно перебрать все элементы цепочки. Это особенно полезно, если вы строите сложный отчет и вам нужно группировать данные по иерархии подразделений.

Метод 4. Использование строковых методов (ПолноеНаименование и ПолныйКод)

Иногда нам не нужны сами ссылки на объекты, а достаточно получить текстовое представление иерархии. В 1С для этого существуют встроенные методы ПолноеНаименование() и ПолныйКод().

Метод ПолноеНаименование() вернет строку, в которой названия подразделений разделены косой чертой (например, "Участок 4 / КНС п. Сиверский-2").

Проанализируем ситуацию, когда нам нужно программно получить список кодов всех родителей. Если в справочнике включено использование иерархических кодов, метод ПолныйКод() вернет строку вида 001/005/012. Разберем, как превратить это в массив:


СтрокаКодов = ТекущееПодразделение.ПолныйКод();
МассивКодов = СтрРазделить(СтрокаКодов, "/");

// Теперь в МассивКодов содержатся коды всех уровней иерархии

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

Метод 5. Особенности работы в СКД (Система компоновки данных)

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

Рассмотрим порядок действий в компоновке:

  1. Добавьте поле Подразделение в набор данных.
  2. На закладке "Настройки" добавьте группировку по этому полю.
  3. Нажмите правой кнопкой мыши на группировку и выберите тип "Иерархия".

Система автоматически определит всех родителей для каждой записи и выведет их в виде дерева. Также в СКД можно использовать функции Уровень() для определения глубины вложенности и Иерархия() для фильтрации данных по всей ветке подразделений.

Важные нюансы для «Бухгалтерии предприятия»

При работе с кодом в конфигурации «Бухгалтерия предприятия 8.3» крайне важно различать два справочника:

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

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

← На главную