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