Входит ли элемент справочника в группу: проверка вручную, запросом и кодом
Содержание
Проверить принадлежность элемента к группе в 1С можно тремя путями. Пользователь ставит в списке или отчёте отбор с видом сравнения «В группе». В запросе пишут условие Ссылка В ИЕРАРХИИ(&Группа). В коде вызывают Элемент.ПринадлежитЭлементу(Группа) — метод вернёт Истина, если элемент лежит в группе на любом уровне вложенности.
Если нужна только непосредственная группа, хватает реквизита Родитель. Разница между «лежит прямо в группе» и «лежит где-то внутри группы» — главный источник ошибок, поэтому дальше каждый способ разобран с этой оговоркой. Всё описанное относится к платформе 8.3 и работает в любой конфигурации с иерархическими справочниками: БП 3.0, УТ 11, ЗУП 3.1, ERP.
Как увидеть группу элемента в списке справочника
Быстрее всего проверить группу глазами — в самом справочнике. Откройте список, например «Номенклатура», и переключите вид отображения.
- В командной панели списка нажмите
Еще → Режим просмотра. - Выберите один из режимов:
- 📁 Иерархический список — показывает содержимое одной группы, вход в группу двойным щелчком, выход — по строке со стрелкой вверх;
- 🌳 Дерево — вся иерархия раскрывается узлами, удобно видеть цепочку вложенности;
- 📄 Список — все элементы плоско, без групп.
- Найдите элемент поиском по строке. В режиме «Дерево» 1С раскроет ветку, в которой он лежит.
В режиме «Список» группа сразу не видна. Её можно вывести колонкой: Еще → Настроить список → Поля, добавьте поле «Родитель» (в некоторых справочниках оно называется «Группа»). Колонка покажет только ближайшую группу, без верхних уровней.
Чтобы узнать полный путь элемента, откройте его карточку: поле «Родитель» (или «Входит в группу») показывает ближайшую группу. Откройте её — и так до верхнего уровня. Для глубокой иерархии удобнее режим «Дерево».
Если у справочника нет групп
Иерархия бывает двух видов, она задаётся в конфигураторе в свойствах справочника:
| Вид иерархии | Что может быть родителем | Есть ли признак «группа» |
|---|---|---|
| Иерархия групп и элементов | Только группа (папка) | Да, реквизит ЭтоГруппа |
| Иерархия элементов | Любой элемент | Нет |
Пример второго вида — подразделения в ряде конфигураций: одно подразделение подчинено другому, отдельных «папок» нет. Проверка принадлежности работает так же, но «группой» в этом случае выступает обычный элемент-родитель.
Отбор «В группе» в списках и отчётах
Когда нужно не проверить один элемент, а увидеть все, что входят в группу, используйте отбор.
В списке справочника или документов:
Еще → Настроить список → Отбор.- Добавьте поле, например «Ссылка» для справочника или «Номенклатура» для табличной части в отчёте.
- В колонке вида сравнения выберите «В группе».
- Укажите группу и нажмите «Завершить редактирование».
В отчёте на СКД (оборотно-сальдовая ведомость, «Валовая прибыль», «Остатки товаров») вид сравнения тот же: в настройках отбора по номенклатуре, контрагенту или статье затрат выбирайте «В группе».
| Вид сравнения | Что попадёт в результат |
|---|---|
| Равно | Ровно указанное значение |
| В группе | Сама группа и всё, что в ней на любом уровне |
| В списке | Перечисленные значения, без раскрытия групп |
| В группе из списка | Содержимое нескольких групп сразу |
Частая ошибка в отчётах — выбрать «Равно» и указать группу. Отчёт окажется пустым: ни одна операция не проводится по группе, только по элементам.
Проверка через запрос: условие В ИЕРАРХИИ
В языке запросов принадлежность проверяет оператор В ИЕРАРХИИ. Он отбирает саму группу и всех её потомков на всех уровнях.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Наименование КАК Наименование
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Ссылка В ИЕРАРХИИ(&Группа)
| И НЕ Номенклатура.ЭтоГруппа";
Запрос.УстановитьПараметр("Группа", Группа);
Выборка = Запрос.Выполнить().Выбрать();
Условие НЕ ЭтоГруппа убирает из результата саму группу и вложенные подгруппы — остаются только элементы.
Проверить один элемент запросом
Если нужен ответ «да/нет» для конкретной ссылки, запрос короче:
Запрос = Новый Запрос(
"ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА КАК Принадлежит
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Ссылка = &Элемент
| И Номенклатура.Ссылка В ИЕРАРХИИ(&Группа)");
Запрос.УстановитьПараметр("Элемент", Элемент);
Запрос.УстановитьПараметр("Группа", Группа);
Принадлежит = НЕ Запрос.Выполнить().Пустой();
Несколько групп и проверка в табличных данных
В параметр можно передать массив групп — В ИЕРАРХИИ(&СписокГрупп) проверит все сразу. Оператор работает не только по самому справочнику, но и по реквизиту-ссылке в документах и регистрах:
|ГДЕ
| ПродажиОбороты.Номенклатура В ИЕРАРХИИ(&СписокГрупп)
Так получают, например, продажи по группе «Бытовая техника» со всеми подгруппами без ручного перечисления.
Проверка в коде: ПринадлежитЭлементу, Родитель и ЭтоГруппа
Во встроенном языке есть три инструмента. Они отвечают на разные вопросы.
| Что нужно узнать | Чем проверять | Уровни |
|---|---|---|
| Лежит ли элемент в группе на любой глубине | Элемент.ПринадлежитЭлементу(Группа) | Все |
| Лежит ли элемент прямо в группе | Элемент.Родитель = Группа | Только ближайший |
| Это группа или элемент | Ссылка.ЭтоГруппа | — |
Метод ПринадлежитЭлементу
Метод есть у ссылки и у объекта иерархического справочника:
&НаСервере
Функция ВходитВГруппу(Элемент, Группа)
Если Элемент = Группа Тогда
Возврат Истина;
КонецЕсли;
Возврат Элемент.ПринадлежитЭлементу(Группа);
КонецФункции
Сравнение Элемент = Группа добавлено намеренно. Метод проверяет подчинённость, а вопрос «входит ли группа сама в себя» в разных задачах решают по-разному. Явная проверка убирает неоднозначность и делает поведение функции таким же, как у В ИЕРАРХИИ.
Вызывайте метод на сервере. Он обращается к базе данных, а в управляемой форме на клиенте методы ссылок недоступны. С клиента передайте ссылки в серверную процедуру формы или в общий модуль с флагом «Сервер».
Реквизит Родитель
Элемент.Родитель возвращает ближайшую группу. У элемента верхнего уровня это пустая ссылка: Справочники.Номенклатура.ПустаяСсылка().
Если Элемент.Родитель = Справочники.Номенклатура.НайтиПоНаименованию("Канцтовары", Истина) Тогда
// элемент лежит непосредственно в группе «Канцтовары»
КонецЕсли;
Поиск группы по наименованию годится для разовой обработки, но не для типового кода: наименования повторяются и меняются. В постоянных алгоритмах храните группу в константе, в настройке или используйте предопределённый элемент.
Признак ЭтоГруппа в форме списка
В форме с динамическим списком тип текущей строки берут из текущих данных, без обращения к базе:
&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
ТекущиеДанные = Элементы.Список.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
Элементы.ФормаЗагрузитьЦены.Доступность = НЕ ТекущиеДанные.ЭтоГруппа;
КонецПроцедуры
Здесь ФормаЗагрузитьЦены — пример имени своей команды на форме, подставьте реальное.
Вложенные уровни: прямой родитель, вся цепочка и глубина
Иногда нужна не проверка «да/нет», а сама структура: на каком уровне лежит элемент, какие группы над ним.
Уровень элемента
Метод Уровень() возвращает номер уровня, верхний уровень — 0.
УровеньЭлемента = Элемент.Уровень();
// 0 — в корне, 1 — внутри одной группы, 2 — в подгруппе и т. д.
Цепочка родителей до корня
Простой цикл по Родитель даёт полный путь:
&НаСервере
Функция ЦепочкаРодителей(Элемент)
Результат = Новый Массив;
Текущий = Элемент.Родитель;
Пока ЗначениеЗаполнено(Текущий) Цикл
Результат.Вставить(0, Текущий);
Текущий = Текущий.Родитель;
КонецЦикла;
Возврат Результат;
КонецФункции
Массив получится от верхней группы к ближайшей. Каждое Текущий.Родитель — отдельное чтение из базы, поэтому для пяти уровней будет пять обращений. На одном элементе это незаметно, в цикле по тысячам строк — заметно.
Итоги по иерархии в запросе
Чтобы получить дерево «группа → подгруппы → элементы» с суммами, используют ИТОГИ ... ПО ... ИЕРАРХИЯ:
|ВЫБРАТЬ
| Остатки.Номенклатура КАК Номенклатура,
| Остатки.КоличествоОстаток КАК Количество
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки
|ИТОГИ
| СУММА(Количество)
|ПО
| Номенклатура ИЕРАРХИЯ
Результат обходят через Выбрать(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией). Имя регистра в примере условное: в БП, УТ и ERP регистры остатков называются по-разному.
Пустые значения, составные типы и битые ссылки
Проверка принадлежности ломается не на самой иерархии, а на «грязных» входных данных. Вот что стоит проверять до вызова.
- 🔲 Пустая группа. Если
Группане заполнена, условие теряет смысл. Решите заранее: пустая группа означает «без ограничения» или «ничего не подходит», и обработайте это явно черезЗначениеЗаполнено(Группа). - 🔀 Составной тип. Реквизит может хранить ссылки разных справочников или
Неопределено. Перед вызовом метода проверьте тип:ТипЗнч(Значение) = Тип("СправочникСсылка.Номенклатура"). Иначе получите ошибку «Метод объекта не обнаружен ». - 💔 Битая ссылка. Если элемент удалён непосредственно, в поле видно
<Объект не найден>. В конфигурациях на БСП проверяйте ссылку функциейОбщегоНазначения.СсылкаСуществует(Ссылка). - 🗑 Пометка удаления. Помеченные на удаление группы и элементы продолжают участвовать в иерархии. Если их нужно исключить, добавьте
НЕ ПометкаУдаленияв запрос. - 🧭 Другой справочник. Сравнение ссылок разных типов всегда даст
Ложь, ошибки не будет — и это хуже, чем ошибка: алгоритм молча «не найдёт» элемент.
Надёжный шаблон функции с защитой от этих случаев:
&НаСервере
Функция ЭлементВГруппе(Значение, Группа)
Если НЕ ЗначениеЗаполнено(Группа) Тогда
Возврат Истина; // пустая группа — без ограничения
КонецЕсли;
Если ТипЗнч(Значение) <> ТипЗнч(Группа) Тогда
Возврат Ложь;
КонецЕсли;
Если НЕ ЗначениеЗаполнено(Значение) Тогда
Возврат Ложь;
КонецЕсли;
Если Значение = Группа Тогда
Возврат Истина;
КонецЕсли;
Возврат Значение.ПринадлежитЭлементу(Группа);
КонецФункции
Первая ветка — пример бизнес-правила. Если в вашей задаче пустая группа значит «ничего», верните Ложь.
Какой способ быстрее и когда что выбирать
Скорость зависит не от метода, а от того, сколько раз вы обращаетесь к базе.
| Способ | Обращений к базе | Где уместен |
|---|---|---|
ПринадлежитЭлементу | 1 на каждый вызов | Проверка одного-двух значений: при записи документа, в обработчике формы |
Цикл по Родитель | По числу уровней на каждый элемент | Построение пути для вывода, не для массовых проверок |
Запрос с В ИЕРАРХИИ | 1 на весь набор | Отборы, отчёты, массовая обработка |
| Состав группы в соответствии | 1 запрос, дальше в памяти | Многократные проверки в одном цикле |
Пример: обработка проверяет 10 000 строк табличной части. С ПринадлежитЭлементу в цикле это 10 000 серверных обращений. Один запрос даёт тот же ответ за одно обращение.
Если проверять приходится внутри цикла, соберите состав группы заранее:
&НаСервере
Функция СоставГруппы(Группа)
Запрос = Новый Запрос(
"ВЫБРАТЬ
| Спр.Ссылка КАК Ссылка
|ИЗ
| Справочник.Номенклатура КАК Спр
|ГДЕ
| Спр.Ссылка В ИЕРАРХИИ(&Группа)");
Запрос.УстановитьПараметр("Группа", Группа);
Состав = Новый Соответствие;
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Состав.Вставить(Выборка.Ссылка, Истина);
КонецЦикла;
Возврат Состав;
КонецФункции
// В цикле:
Состав = СоставГруппы(Группа);
Для Каждого Строка Из Объект.Товары Цикл
Если Состав[Строка.Номенклатура] = Истина Тогда
// строка относится к группе
КонецЕсли;
КонецЦикла;
Поиск в Соответствии по ключу идёт в памяти и не трогает базу.
💡 Ещё лучше — вообще не тянуть строки на сервер приложений. Если табличная часть уже записана, сделайте соединение с ней прямо в запросе и отберите нужные строки условием В ИЕРАРХИИ.
В ИЕРАРХИИ по очень глубоким и широким деревьям тоже не бесплатный: платформа раскрывает иерархию по уровням. Если тот же отбор выполняется тысячи раз в день, вынесите состав группы в кэш (модуль с повторным использованием возвращаемых значений) и сбрасывайте его при изменении справочника.
Мини-кейс: скидка на группу товаров
Задача: при записи заказа дать скидку 5% на всё из группы «Расходники», включая подгруппы. В заказе 40 строк.
- ❌ Неудачно: 40 вызовов
ПринадлежитЭлементу, по одному на строку. - ✅ Удачно: один запрос с
В ИЕРАРХИИпо номенклатуре из табличной части, результат — список строк для скидки.
Код короче, а время записи документа не растёт вместе с числом строк.
Частые вопросы
Входит ли сама группа в результат В ИЕРАРХИИ?
Ссылка <> &Группа или НЕ ЭтоГруппа.Как проверить, что элемент лежит в корне справочника?
НЕ ЗначениеЗаполнено(Элемент.Родитель) или Элемент.Уровень() = 0.Можно ли использовать В ИЕРАРХИИ для документов?
Сработает ли проверка, если элемент перенесли в другую группу?
Родитель в базе. Старые отчёты пересчитаются по новой структуре, если только они не сохранены готовым результатом.Как проверить принадлежность сразу к нескольким группам?
В ИЕРАРХИИ(&СписокГрупп). В отборе отчёта выберите вид сравнения «В группе из списка».