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

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

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

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

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

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

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

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

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

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

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

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

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

Группа = Справочники.Номенклатура.НайтиПоНаименованию("Электроника");

Элемент = Справочники.Номенклатура.НайтиПоКоду("000123");

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

Сообщить("Элемент входит в группу или её подгруппы");

КонецЕсли;

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

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

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

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

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

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

КонецЕсли;

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

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

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

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

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

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

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

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

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

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

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

ВЫБРАТЬ

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

ИЗ

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

ГДЕ

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

И НЕ Номенклатура.ЭтоГруппа

Параметр &Группа принимает ссылку на группу, массив ссылок или список значений — можно проверять принадлежность сразу нескольким веткам. Условие НЕ Номенклатура.ЭтоГруппа исключает сами группы из выборки, если нужны только элементы.

Если нужна проверка только прямого родителя без подгрупп, в запросе используется обычное равенство: Номенклатура.Родитель = &Группа. Такое условие быстрее, потому что не требует обхода иерархии.

Порядок действий для проверки в запросе
  1. 1
    Определите, нужна ли проверка с учётом подгрупп или только прямой родитель
  2. 2
    Получите ссылку на группу через НайтиПоНаименованию, НайтиПоКоду или из параметра
  3. 3
    Сформируйте запрос с В ИЕРАРХИИ(&Группа) либо Родитель = &Группа
  4. 4
    Установите параметр запроса: Запрос.УстановитьПараметр("Группа", ГруппаСсылка)
  5. 5
    Выполните запрос и проверьте, что выборка не пустая и содержит ожидаемые элементы

Проверка в динамических списках и СКД

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

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

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

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

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

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

Третья группа проблем связана с предопределёнными группами и обменами: после обмена данными ссылка на группу может отличаться от ожидаемой, если поиск шёл по наименованию, а наименования в базах расходятся. Надёжнее искать группу по коду или хранить ссылку в константе/параметре, а не «зашивать» наименование в код.

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

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

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

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

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

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

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

Проверка возвращает Истина / элемент есть в выборке

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

Ложь или пустая выборка — проверьте, что передана ссылка, а не строка

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

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

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

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

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

Проверка возвращает Ложь

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

Истина — возможно, в отборе выбран вид сравнения «В группе из списка» с лишними группами

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

Чем «В группе» отличается от «В группе из списка» в отборах?

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

Можно ли проверить принадлежность без обращения к базе?

Только если данные уже прочитаны: например, у вас есть объект справочника или выборка из запроса с полем Родитель. По одной ссылке без чтения из базы определить родителя нельзя — платформа выполнит обращение неявно при обращении к реквизиту через точку.

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

Метод существует у иерархических справочников и планов видов характеристик. У планов счетов иерархия устроена иначе (через родительские счета и порядок в коде), поэтому там проверку выполняют через родителя счёта или маску кода.

Почему запрос с В ИЕРАРХИИ возвращает пустой результат?

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

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

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

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

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

Итог

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

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