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