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

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

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

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

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

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

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

Что такое родитель в иерархическом справочнике

Родитель — это служебный реквизит Родитель (Parent), который автоматически присутствует у каждого элемента справочника, если в конфигураторе для справочника включён вид иерархии. У элементов верхнего уровня родитель пустой — это пустая ссылка соответствующего типа справочника.

Справочник может иметь два вида иерархии: иерархия групп и элементов (группы выступают папками и не несут собственных данных) или иерархия элементов (любой элемент может быть родителем другого). От вида иерархии зависит, может ли родитель быть обычным элементом с данными или только группой с признаком ЭтоГруппа = Истина.

Важно понимать разницу между объектом и ссылкой: реквизит Родитель доступен и у объекта (СправочникОбъект), и у ссылки (СправочникСсылка). При обращении через ссылку платформа неявно выполняет запрос к базе, поэтому в циклах такие обращения нужно минимизировать.

Получение ближайшего родителя через реквизит Родитель

Самый простой случай — нужен непосредственный родитель элемента. Достаточно обратиться к реквизиту:

РодительЭлемента = ЭлементСсылка.Родитель;

Если РодительЭлемента.Пустая() Тогда

// Элемент находится на верхнем уровне иерархии

КонецЕсли;

Если работа идёт с объектом (например, в обработчике ПередЗаписью модуля объекта), обращение выглядит так же: ЭтотОбъект.Родитель или просто Родитель. В форме элемента родитель доступен через Объект.Родитель.

Через точку можно подняться сразу на несколько уровней: ЭлементСсылка.Родитель.Родитель вернёт «деда» элемента. Однако такая запись небезопасна: если промежуточный родитель пуст, обращение к его реквизиту вернёт пустую ссылку без ошибки, но дальнейшая цепочка может дать неожиданный результат. Перед длинными цепочками проверяйте каждое звено на пустоту.

Получение всей цепочки родителей до корня

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

Функция ПолучитьВсехРодителей(ЭлементСсылка)

Родители = Новый Массив;

ТекущийРодитель = ЭлементСсылка.Родитель;

Пока Не ТекущийРодитель.Пустая() Цикл

Родители.Добавить(ТекущийРодитель);

ТекущийРодитель = ТекущийРодитель.Родитель;

КонецЦикла;

Возврат Родители;

КонецФункции

Массив заполняется от ближайшего родителя к корню. Если нужен порядок «от корня к элементу», разверните массив или вставляйте элементы в начало через Вставить(0, ...).

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

Порядок действий для получения цепочки родителей
  1. 1
    Получите ссылку на элемент, для которого ищутся родители
  2. 2
    Возьмите ЭлементСсылка.Родитель и проверьте его на пустоту методом Пустая()
  3. 3
    В цикле добавляйте каждого родителя в массив и поднимайтесь на уровень выше
  4. 4
    Завершите цикл, когда родитель окажется пустой ссылкой
  5. 5
    Проверьте результат: количество родителей должно совпадать с глубиной элемента в дереве

Проверка вхождения элемента в группу

Частая практическая задача — не собрать всех родителей, а ответить на вопрос «находится ли элемент внутри заданной группы на любом уровне». Для этого есть два штатных инструмента.

Метод ПринадлежитЭлементу

Метод ПринадлежитЭлементу(ГруппаСсылка) вызывается у объекта справочника и возвращает Истина, если элемент находится в указанной группе с учётом всех уровней вложенности:

Если СправочникОбъект.ПринадлежитЭлементу(ГруппаСсылка) Тогда

// Элемент входит в группу или её подгруппы

КонецЕсли;

Ограничение метода — он доступен только у объекта, а не у ссылки. Если у вас есть только ссылка, придётся либо получать объект (что дорого при массовой обработке), либо использовать запрос.

Запрос с конструкцией В ИЕРАРХИИ

В запросах проверка выполняется оператором В ИЕРАРХИИ. Он работает со ссылками и не требует получения объектов:

ВЫБРАТЬ

Номенклатура.Ссылка

ИЗ

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

ГДЕ

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

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

Сравнение способов

Реквизит Родитель

Подходит для разового получения ближайшего родителя. Неэффективен в циклах из-за неявных запросов.

Цикл по уровням

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

ПринадлежитЭлементу

Простая проверка вхождения в группу, но требует объект, а не ссылку.

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

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

Получение родителей запросом для массовой обработки

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

ВЫБРАТЬ

Товары.Ссылка КАК Элемент,

Товары.Родитель КАК Группа,

Товары.Родитель.Наименование КАК ГруппаНаименование

ИЗ

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

Платформа выполнит такой запрос одним обращением к СУБД. Обращение Родитель.Наименование внутри запроса — это соединение таблиц, а не отдельный запрос, поэтому оно безопасно для производительности.

Если нужен родитель конкретного уровня (например, группа верхнего уровня для каждого элемента), одним запросом задача решается через последовательные соединения таблицы справочника самой с собой по числу уровней либо через итеративную обработку выборки. Универсального оператора «дать предка N-го уровня» в языке запросов 1С нет.

Родитель в динамических списках и СКД

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

В СКД (системе компоновки данных) поле Родитель доступно в наборе данных, а для иерархических отчётов используется связь «родитель–элемент» в настройках группировки: отчёт сам строит дерево, если указать иерархическую группировку по ссылке. Для отбора по ветке дерева в параметрах СКД применяйте вид сравнения «В иерархии».

Если в отчёте нужно показать путь элемента (например, «Инструменты / Ручной инструмент / Отвёртки»), СКД сама такую строку не построит — потребуется вычисляемое поле или предварительная сборка путей во временную таблицу в запросе набора данных.

Типичные ошибки
01
Обращение к Родитель.Родитель без проверки на пустоту: у элемента верхнего уровня цепочка обрывается, и логика получает пустые ссылки там, где ожидала группу
02
Использование ПринадлежитЭлементу у ссылки: метод есть только у объекта, попытка вызвать его у СправочникСсылка приводит к ошибке времени выполнения
03
Сравнение родителя со строкой наименования вместо ссылки: Родитель — это ссылка, сравнивать нужно со ссылкой на группу
04
Получение объекта через ПолучитьОбъект() только ради чтения родителя: это лишняя нагрузка, реквизит доступен и у ссылки
05
Игнорирование вида иерархии: в справочнике с иерархией элементов родителем может быть обычный элемент, а не группа, что ломает проверки вида Родитель.ЭтоГруппа

Особые случаи: планы видов характеристик и внешние источники

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

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

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

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

Ближайший родитель
Норма

Реквизит Родитель содержит ссылку на ожидаемую группу

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

Родитель пуст, хотя в дереве элемент визуально находится в группе — проверьте, не отключена ли иерархия или не перенесён ли элемент

Цепочка родителей
Норма

Количество элементов массива равно глубине элемента в дереве

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

Цепочка короче ожидаемой — где-то в середине пустая ссылка или битая ссылка

Проверка В ИЕРАРХИИ
Норма

Запрос возвращает элементы из группы и всех её подгрупп

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

Возвращаются только элементы первого уровня — вероятно, использовано равенство по Родителю вместо В ИЕРАРХИИ

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

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

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

Почему Родитель возвращает пустую ссылку, хотя элемент в группе?

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

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

Нет. Данные об иерархии хранятся в базе, поэтому любое получение родителя — явное (запрос) или неявное (обращение через точку) — обращается к ней. Минимизировать число обращений можно, выбирая родителя в основном запросе выборки.

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

Передайте в параметр запроса список групп и используйте условие Ссылка В ИЕРАРХИИ(&СписокГрупп) — оператор работает и со списком значений. Без запроса можно проверить каждую группу методом ПринадлежитЭлементу в цикле.

Чем отличается В ИЕРАРХИИ от сравнения по Родителю?

Сравнение Родитель = &Группа находит только элементы первого уровня вложенности. В ИЕРАРХИИ учитывает все уровни: элементы подгрупп любой глубины тоже попадут в выборку.

Работает ли ПринадлежитЭлементу на клиенте?

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

Итог

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

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