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

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

Как проверить родителя элемента в 1С

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

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

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

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

Что такое родитель элемента и где он хранится

Родитель — это группа (папка) иерархического справочника или плана видов характеристик, в которую входит элемент. В объекте справочника значение хранится в стандартном реквизите Родитель и доступно как у объекта (СправочникОбъект), так и у ссылки (СправочникСсылка) без явного обращения к базе за объектом.

Важно понимать: свойство Родитель всегда содержит только непосредственную группу верхнего уровня вложенности. Если элемент лежит по пути «Номенклатура → Материалы → Металлопрокат → Арматура», то родителем «Арматуры» будет «Металлопрокат», а не «Материалы» и не корень справочника.

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

Как получить и проверить родителя через свойство Родитель

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

Если Элемент.Родитель = ГруппаМатериалы Тогда

// Элемент лежит непосредственно в группе "Материалы"

КонецЕсли;

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

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

КонецЕсли;

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

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

Проверка вхождения в группу на любом уровне: ПринадлежитЭлементу

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

Если ЭлементНоменклатуры.ПринадлежитЭлементу(ГруппаМатериалы) Тогда

// Элемент входит в "Материалы" или в любую её подгруппу

КонецЕсли;

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

Проверка родителя в запросе: В ИЕРАРХИИ и прямое сравнение

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

ВЫБРАТЬ

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

ИЗ

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

ГДЕ

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

Если нужен строго непосредственный родитель, используют обычное равенство: ГДЕ Номенклатура.Родитель = &Группа. Такой запрос быстрее, чем В ИЕРАРХИИ, и его проще оптимизирует СУБД.

Дополнительные полезные приёмы в запросе:

  • Номенклатура.Родитель = ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка) — отбор элементов в корне справочника;
  • Номенклатура.ЭтоГруппа — разделение групп и элементов в выборке;
  • соединение с родителем для вывода его наименования: Номенклатура.Родитель.Наименование КАК Группа.

Сравнение вариантов

Элемент.Родитель = Группа

Только непосредственный родитель. Быстро, без обращения к БД, но не видит вложенность глубже одного уровня.

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

Вся цепочка вложенности для одиночного элемента. Удобно в коде, дорого в массовых циклах.

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

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

Отбор динамического списка

Для форм выбора и списков: отбор по полю Родитель или Ссылка В ИЕРАРХИИ без программного кода.

Проверка родителя в форме и динамическом списке

В формах выбора и списках справочников проверка родителя обычно реализуется отбором, а не кодом. Для динамического списка можно установить отбор программно:

ЭлементОтбора = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));

ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Родитель");

ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.ВИерархии;

ЭлементОтбора.ПравоеЗначение = ГруппаМатериалы;

ЭлементОтбора.Использование = Истина;

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

Если форма управляемая и список уже содержит стандартную иерархию, помните о свойстве списка «Режим отображения»: при режиме «Дерево» отбор по родителю может визуально конфликтовать с раскрытием групп. Тестируйте отбор в том режиме, в котором работает пользователь.

Порядок действий для типовой проверки
  1. 1
    Определите, что нужно: непосредственный родитель или вся цепочка вложенности.
  2. 2
    Для одиночного элемента в коде используйте сравнение Родителя или ПринадлежитЭлементу().
  3. 3
    Для выборки элементов напишите запрос с Родитель = &Группа или В ИЕРАРХИИ(&Группа).
  4. 4
    Для формы списка добавьте отбор динамического списка без программного обхода.
  5. 5
    Проверьте поведение на элементе из корня справочника и на самой группе.
  6. 6
    Прогоните проверку на тестовой копии базы перед переносом в рабочую.

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

Большинство проблем с проверкой родителя связаны не с синтаксисом, а с неверными предположениями о данных. Разберём основные.

Первая ошибка — сравнение родителя с Неопределено. У элемента в корне справочника родитель не Неопределено, а пустая ссылка. Правильная проверка: Если Элемент.Родитель.Пустая() Тогда.

Вторая ошибка — ожидание, что сравнение Родитель = Группа найдёт элементы во вложенных подгруппах. Оно не найдёт: равенство проверяет только один уровень. Для вложенности нужен ПринадлежитЭлементу() или В ИЕРАРХИИ.

Третья ошибка — проверка по наименованию группы. Группы «Услуги» могут существовать в разных ветках справочника, и поиск по имени вернёт не ту ссылку. Всегда работайте со ссылками, полученными по коду, предопределённому имени или явно переданными параметром.

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

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

Как проверить результат и границы самостоятельной работы

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

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

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

Элемент в целевой группе
Норма

Проверка возвращает Истина

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

Возвращает Ложь — проверьте тип ссылки и вид сравнения

Элемент во вложенной подгруппе
Норма

В ИЕРАРХИИ и ПринадлежитЭлементу возвращают Истина

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

Ложь — вероятно, использовано простое равенство Родителя

Элемент в корне справочника
Норма

Родитель.Пустая() = Истина, код не падает

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

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

Производительность на большой выборке
Норма

Запрос выполняется за приемлемое время

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

Цикл с ПринадлежитЭлементу — переписать на запрос

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

Итог

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

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

Часто задаваемые вопросы

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

Используйте проверку Элемент.Родитель.Пустая() или НЕ ЗначениеЗаполнено(Элемент.Родитель). Сравнение с Неопределено не подходит: родитель всегда имеет ссылочный тип и у корневых элементов содержит пустую ссылку, а не Неопределено.

Чем ПринадлежитЭлементу() отличается от сравнения Родителя?

Сравнение Элемент.Родитель = Группа проверяет только один уровень — непосредственную папку. Метод ПринадлежитЭлементу() проходит всю цепочку вверх и возвращает Истина, если группа встречается на любом уровне вложенности, включая случай, когда элемент и есть сама проверяемая группа.

Как в запросе получить элементы без родителя?

Добавьте условие: ГДЕ Номенклатура.Родитель = ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка). Подставьте имя своего справочника. Такой запрос часто используют для поиска элементов, не распределённых по группам.

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

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

Почему В ИЕРАРХИИ в запросе не находит элементы, хотя группа указана верно?

Частые причины: передана ссылка не того типа (например, группа из другого справочника), передана пустая ссылка, либо в параметр попало наименование вместо ссылки. Проверьте тип и заполненность параметра &Группа перед выполнением запроса, например выведя его в отладчике.

Как быстро посмотреть родителя элемента без программирования?

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