В процессе разработки часто возникает задача, когда по конкретному элементу справочника необходимо восстановить всю цепочку его иерархии — от самого элемента до корневой группы. Это может понадобиться для вывода полного пути в отчетах, быстрого анализа данных или применения настроек, заданных для родительских групп верхнего уровня — для этого есть обработка выгрузки иерархии справочников в Excel и CSV.
Давайте подробно разберем, как решить эту задачу в системе 1С:Предприятие. Мы рассмотрим два основных подхода: использование объектной модели (через свойства ссылки) и использование языка запросов, а также проанализируем, в каких случаях каждый из методов будет эффективнее.
Самый очевидный и простой для понимания способ — это использование свойства Родитель у ссылки справочника. Подобное получение значения реквизита по ссылке на любом уровне вложенности позволяет нам подниматься вверх по иерархии в цикле, пока не достигнем корня (пустой ссылки).
Рассмотрим готовую функцию, которая принимает ссылку на элемент и возвращает массив всех его родителей.
Алгоритм действий:
Посмотрим на реализацию этого алгоритма в коде:
Функция ПолучитьМассивРодителей(ЭлементСпр)
// Создаем массив для хранения ссылок на группы-родители
МассивРодителей = Новый Массив;
// Получаем первого родителя
ТекущийРодитель = ЭлементСпр.Родитель;
// Выполняем цикл, пока не дойдем до вершины иерархии (пустая ссылка)
Пока Не ТекущийРодитель.Пустая() Цикл
// Добавляем найденного родителя в массив
МассивРодителей.Добавить(ТекущийРодитель);
// Переходим на уровень выше
ТекущийРодитель = ТекущийРодитель.Родитель;
КонецЦикла;
Возврат МассивРодителей;
КонецФункции
Этот код эффективен для обработки одиночных элементов. Однако здесь есть важный нюанс, касающийся производительности.
Важное предостережение:
Обращение к свойству через точку (например, Родитель.Родитель) при выполнении кода на клиенте вызывает множественные вызовы сервера. Если иерархия глубокая, это может привести к заметным задержкам. Оценивая производительность различных способов обхода данных, данный код настоятельно рекомендуется выполнять на сервере.
Многие разработчики ошибочно полагают, что иерархия в запросах работает только "вниз". Однако, чтобы получить родителей (движение "вверх"), мы можем использовать механизм итогов. Для облегчения этой задачи существует интерактивное формирование текста запроса для получения родителей всех уровней, что значительно ускоряет написание кода.
Если мы сделаем запрос к справочнику с отбором по конкретной ссылке и добавим конструкцию ИТОГИ ПО ... ИЕРАРХИЯ, платформа 1С автоматически построит дерево, в которое войдут все предки искомого элемента.
Давайте проанализируем, как это работает. При использовании итогов по иерархии в результат запроса неявно включаются все родительские записи, необходимые для построения иерархической структуры результата.
Пример текста запроса:
ВЫБРАТЬ
Спр.Ссылка КАК Ссылка
ИЗ
Справочник.Номенклатура КАК Спр
ГДЕ
Спр.Ссылка = &СсылкаНаЭлемент
ИТОГИ ПО
Ссылка ИЕРАРХИЯ
Для быстрой проверки и отладки подобных конструкций идеально подойдет консоль запросов для управляемых форм, которая поддерживает работу с иерархическими итогами — для этого подойдёт инструмент пошаговой отладки кода 1С.
После выполнения запроса результат нужно обойти особым образом. Выборка должна производиться с типом обхода ПоГруппировкамСИерархией. В этом случае вы получите дерево значений, где верхним уровнем будет корневая группа, а вложенными — путь до вашего элемента — для этого есть печатная форма с иерархией групп номенклатуры.
Этот метод сложнее в реализации обхода результата, но он незаменим в следующих случаях:
Если в конфигурации справочник настроен определенным образом, существует еще один интересный метод. Если для справочника установлена длина кода больше 0 и используется иерархия, платформа 1С предоставляет метод ПолныйКод().
Этот метод возвращает строку, содержащую коды всех родителей, разделенные символом разделителя (обычно "/").
Пример строки полного кода: КодГруппы1/КодГруппы2/КодЭлемента.
Разберем, как это можно использовать. Если вам нужны не ссылки, а просто идентификаторы или коды родителей, вы можете получить эту строку и разбить ее функцией СтрРазделить. Это работает очень быстро, так как не требует множественных обращений к базе данных для чтения каждой ссылки по отдельности.
Подведем итоги и выберем оптимальный инструмент для вашей задачи: