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

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

Как проверить вхождение элемента в группу в 1С

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

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

Главная сложность в том, что «вхождение в группу» бывает двух видов: элемент лежит непосредственно в группе (родитель равен группе) либо элемент находится в группе с учётом всех вложенных подгрупп. Для первого случая достаточно сравнения родителя, для второго нужны специальные механизмы платформы.

Ниже разобраны все рабочие способы: метод ПринадлежитЭлементу, сравнение по родителю, оператор запроса В ИЕРАРХИИ, а также проверка в пользовательском режиме без программирования. Отдельно рассмотрены типичные ошибки, из-за которых проверка «не видит» вложенные элементы или наоборот захватывает лишнее.

Как устроена иерархия справочников в 1С

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

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

Ещё один нюанс — предопределённые группы и служебные родители. Если проверка строится на сравнении наименований, а не ссылок, она сломается при первом же переименовании папки. Все надёжные способы работают только со ссылками.

Проверка через метод ПринадлежитЭлементу

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

ЭлементОбъект = СсылкаНаЭлемент.ПолучитьОбъект();

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

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

КонецЕсли;

Обратите внимание: метод вызывается у объекта, а не у ссылки, поэтому приходится выполнять ПолучитьОбъект(). Это создаёт объект в памяти и при массовой проверке тысяч элементов даёт заметную нагрузку. Для проверки одного-двух элементов способ удобен, для пакетной обработки лучше использовать запрос.

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

bsl
Если СправочникОбъект.ПринадлежитЭлементу(ГруппаНоменклатуры) Тогда
    Сообщить("Элемент входит в группу с учетом подгрупп");
КонецЕсли;

Проверка через сравнение родителя

Если задача — убедиться, что элемент лежит непосредственно в конкретной группе, достаточно сравнить его реквизит Родитель со ссылкой на группу:

Если СсылкаНаЭлемент.Родитель = ГруппаПроверки Тогда

// элемент лежит прямо в этой группе

КонецЕсли;

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

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

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

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

Простой код, учитывает подгруппы. Ограничение: нужен ПолучитьОбъект(), медленно при массовой проверке.

Сравнение Родителя

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

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

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

Проверка запросом с оператором В ИЕРАРХИИ

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

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

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

|ИЗ

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

|ГДЕ

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

Запрос.УстановитьПараметр("Группа", ГруппаПроверки);

Результат = Запрос.Выполнить();

Чтобы проверить вхождение одного конкретного элемента, добавьте условие на ссылку и используйте Результат.Пустой() как признак: пустой результат — элемент не входит в группу. Для отбора в динамическом списке или СКД тот же оператор указывается в отборе, и платформа сама строит эффективный SQL-запрос.

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

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

Проверка в пользовательском режиме без кода

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

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

Третий вариант — открыть карточку элемента и посмотреть поле «Родитель» (или «Группа»). Оно показывает только ближайшую папку, поэтому для проверки глубокой вложенности придётся пройти по цепочке родителей вверх. Это нормально для разовой проверки, но не для регулярного контроля.

Типичные ошибки и ограничения

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

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

Третья группа проблем связана с производительностью: вызов ПринадлежитЭлементу в цикле по тысячам элементов приводит к тысячам вызовов ПолучитьОбъект() и заметному падению скорости. Массовые проверки всегда переводите на запрос с В ИЕРАРХИИ.

Типичные ошибки
01
Сравнение Родителя вместо В ИЕРАРХИИ — элементы из подгрупп не попадают в проверку
02
Сравнение групп по наименованию — проверка ломается при переименовании папки или совпадении имён
03
ПринадлежитЭлементу в цикле по большой выборке — резкое падение производительности из-за ПолучитьОбъект()
04
Проверка без учёта пометки удаления — в результат попадают помеченные на удаление элементы подгрупп

Отдельно отметим пометку удаления: В ИЕРАРХИИ не фильтрует помеченные элементы автоматически. Если логика должна игнорировать помеченные на удаление объекты, добавьте в запрос условие НЕ Номенклатура.ПометкаУдаления.

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

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

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

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

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

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

Все три способа возвращают «истина»

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

Запрос не находит элемент — проверьте параметр и вид иерархии

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

ПринадлежитЭлементу и В ИЕРАРХИИ — «истина», сравнение родителя — «ложь»

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

В ИЕРАРХИИ возвращает «ложь» — возможно, передана не та ссылка группы

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

Все способы возвращают «ложь»

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

Сравнение по наименованию даёт «истина» — замените на сравнение ссылок

Итог

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

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

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

Чем ПринадлежитЭлементу отличается от В ИЕРАРХИИ?

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

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

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

Работает ли проверка, если у справочника иерархия элементов, а не групп?

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

Можно ли проверить вхождение сразу в несколько групп?

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

Почему В ИЕРАРХИИ возвращает помеченные на удаление элементы?

Оператор не фильтрует пометку удаления автоматически — это нормальное поведение платформы. Если помеченные объекты не должны попадать в результат, добавьте в условие запроса НЕ Ссылка.ПометкаУдаления.

Как проверить вхождение в группу в отборе динамического списка?

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