К статье
Практический материал

Разработка и Конфигурация · 9 мин

Как получить всех родителей справочника в 1С

Как получить всех родителей элемента иерархического справочника 1С: запрос с ИЕРАРХИЯ, рекурсивный обход через Родитель, примеры кода, ошибки и проверка результата.

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

Существует два рабочих подхода: запрос с конструкцией ИЕРАРХИЯ, который возвращает всю цепочку одним обращением к базе, и программный обход в цикле через свойство Родитель. Первый быстрее и предпочтительнее в серверном коде и отчётах, второй проще для понимания и удобен, когда на каждом уровне нужно выполнить дополнительную логику.

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

Как устроена иерархия справочника и что именно мы получаем

Иерархический справочник в 1С хранит связь «элемент — родитель» в стандартном реквизите Родитель. У элементов верхнего уровня родитель пустой (пустая ссылка). Глубина вложенности не ограничена платформой жёстко, поэтому цепочка родителей может состоять как из одного уровня, так и из десятка.

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

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

Получение всех родителей запросом с конструкцией ИЕРАРХИЯ

Самый производительный способ — запрос к таблице справочника с условием ГДЕ Ссылка В ИЕРАРХИИ(&Ссылка). Однако здесь есть тонкость: В ИЕРАРХИИ возвращает сам элемент и всех его потомков, а не родителей. Чтобы получить родителей, логику разворачивают: выбирают те элементы, для которых исходная ссылка находится в их иерархии.

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

bsl
Функция ПолучитьВсехРодителей(Элемент)
	Родители = Новый Массив;
	ТекущийРодитель = Элемент.Родитель;
	Пока ЗначениеЗаполнено(ТекущийРодитель) Цикл
		Родители.Добавить(ТекущийРодитель);
		ТекущийРодитель = ТекущийРодитель.Родитель;
	КонецЦикла;
	Возврат Родители;
КонецФункции

Пример запроса, возвращающего родителей элемента (для справочника «Номенклатура»):

ВЫБРАТЬ

Номенклатура.Ссылка КАК Родитель,

Номенклатура.Наименование

ИЗ

Справочник.Номенклатура КАК Номенклатура

ГДЕ

&Элемент В ИЕРАРХИИ(Номенклатура.Ссылка)

И Номенклатура.Ссылка <> &Элемент

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

Получение родителей программным обходом в цикле

Цикл через Родитель — самый наглядный способ. Начинаем с элемента, берём его родителя, затем родителя родителя, и так до тех пор, пока не встретим пустую ссылку. Каждая итерация — одно обращение к базе (точнее, к кэшу объекта), поэтому при глубокой иерархии и массовой обработке способ уступает запросу.

Доступ к реквизиту Родитель возможен как у объекта СправочникОбъект, так и напрямую через ссылку — платформа выполнит неявный запрос. Через ссылку «разыменование» работает, но каждое обращение ТекущийРодитель.Родитель — это отдельное чтение, что стоит учитывать в циклах по тысячам элементов.

Если нужна строка пути, собирайте её в том же цикле, добавляя наименования через разделитель. Помните, что первым в массиве окажется ближайший родитель — для пути «от корня к элементу» массив нужно обойти в обратном порядке.

Какой способ выбрать в разных сценариях

Выбор зависит от объёма данных, места выполнения кода и того, что дальше происходит с результатом. Одиночный элемент в форме — допустим и цикл; пакетная обработка или отчёт — только запрос или временная таблица.

Сравнение подходов

Запрос с В ИЕРАРХИИ

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

Цикл через Родитель

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

Рекурсивная функция

Читаемый вариант цикла для глубокой иерархии. Ограничение — глубина стека при патологически глубоких ветках и риск зацикливания при порче данных.

Для СКД и динамических списков используйте именно конструкцию В ИЕРАРХИИ в параметрах отбора — она выполняется на уровне СУБД и не требует кода. Для обменов, где нужен полный путь каждого элемента, выгоднее один раз выгрузить весь справочник с родителями в соответствие и строить цепочки в памяти.

Типичные ошибки и как их избежать

Типичные ошибки
01
Использование В ИЕРАРХИИ(&Ссылка) для поиска родителей — оператор возвращает потомков, а не предков, в результате получают дочерние элементы вместо цепочки вверх.
02
Отсутствие проверки на пустого родителя — в массив попадает пустая ссылка или цикл завершается ошибкой при обращении к реквизиту пустой ссылки.
03
Цикл по Родитель внутри большой выборки без кэширования — тысячи лишних обращений к базе и заметное падение производительности.
04
Игнорирование вида иерархии — при иерархии групп и элементов попытка искать детей у обычного элемента бессмысленна, а запросы строятся с учётом ЭтоГруппа.
05
Зацикливание при повреждённых данных, где элемент ссылается сам на себя или образуется кольцо — добавляйте счётчик максимальной глубины как защиту.

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

Как проверить, что цепочка родителей собрана правильно

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

Контрольные точки

Как проверить результат

Количество родителей в результате
Норма

Совпадает с числом уровней в дереве справочника для этого элемента

Тревожный признак

Лишняя пустая ссылка в конце или отсутствует корневая группа

Порядок элементов цепочки
Норма

Первым идёт ближайший родитель, последним — корень (или наоборот, если порядок развёрнут осознанно)

Тревожный признак

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

Элемент верхнего уровня
Норма

Функция возвращает пустой массив без ошибок

Тревожный признак

Ошибка обращения к реквизиту или пустая ссылка в результате

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

Частые вопросы

Как получить родителей в виде строки «Группа / Подгруппа / Элемент»?

Соберите массив родителей циклом, разверните его в обратном порядке и соедините наименования через разделитель с помощью СтрСоединить. Наименование самого элемента добавьте в конец строки.

Работает ли В ИЕРАРХИИ в СКД и динамических списках?

Да, конструкция поддерживается в отборах СКД и динамических списков. Передайте ссылку в параметр и используйте условие «В ИЕРАРХИИ(&Параметр)» — отбор выполнится на уровне СУБД без дополнительного кода.

Как получить только родителя определённого уровня, например самого верхнего?

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

Почему запрос с В ИЕРАРХИИ работает медленно на большом справочнике?

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

Чем отличается получение родителей у справочника с иерархией элементов?

Родителем может быть любой элемент, а не только группа, поэтому проверка ЭтоГруппа в логике не нужна. Сами приёмы — цикл через Родитель и запрос — работают одинаково.

Можно ли получить родителей на клиенте без вызова сервера?

Нет, чтение реквизита Родитель требует обращения к данным базы. Вынесите функцию в серверный общий модуль и вызывайте её с клиента, передавая ссылку на элемент.

Итог

Что важно запомнить

Всех родителей элемента получают либо циклом через Родитель с проверкой на пустую ссылку, либо запросом с развёрнутым условием В ИЕРАРХИИ. Для массовой обработки выбирайте запрос или кэширование в памяти, для одиночных элементов достаточно цикла. Всегда защищайтесь от пустой ссылки и кольцевых ссылок, а результат проверяйте на элементе с известным положением в дереве.