Входит ли элемент справочника в группу: проверка вручную, запросом и кодом

· 9 мин

Содержание

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

Если нужна только непосредственная группа, хватает реквизита Родитель. Разница между «лежит прямо в группе» и «лежит где-то внутри группы» — главный источник ошибок, поэтому дальше каждый способ разобран с этой оговоркой. Всё описанное относится к платформе 8.3 и работает в любой конфигурации с иерархическими справочниками: БП 3.0, УТ 11, ЗУП 3.1, ERP.

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

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

  1. В командной панели списка нажмите Еще → Режим просмотра.
  2. Выберите один из режимов:
    • 📁 Иерархический список — показывает содержимое одной группы, вход в группу двойным щелчком, выход — по строке со стрелкой вверх;
    • 🌳 Дерево — вся иерархия раскрывается узлами, удобно видеть цепочку вложенности;
    • 📄 Список — все элементы плоско, без групп.
  3. Найдите элемент поиском по строке. В режиме «Дерево» 1С раскроет ветку, в которой он лежит.

В режиме «Список» группа сразу не видна. Её можно вывести колонкой: Еще → Настроить список → Поля, добавьте поле «Родитель» (в некоторых справочниках оно называется «Группа»). Колонка покажет только ближайшую группу, без верхних уровней.

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

Если у справочника нет групп

Иерархия бывает двух видов, она задаётся в конфигураторе в свойствах справочника:

Вид иерархииЧто может быть родителемЕсть ли признак «группа»
Иерархия групп и элементовТолько группа (папка)Да, реквизит ЭтоГруппа
Иерархия элементовЛюбой элементНет

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

Отбор «В группе» в списках и отчётах

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

В списке справочника или документов:

  1. Еще → Настроить список → Отбор.
  2. Добавьте поле, например «Ссылка» для справочника или «Номенклатура» для табличной части в отчёте.
  3. В колонке вида сравнения выберите «В группе».
  4. Укажите группу и нажмите «Завершить редактирование».

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

Вид сравненияЧто попадёт в результат
РавноРовно указанное значение
В группеСама группа и всё, что в ней на любом уровне
В спискеПеречисленные значения, без раскрытия групп
В группе из спискаСодержимое нескольких групп сразу

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

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

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

Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
|	Номенклатура.Ссылка КАК Ссылка,
|	Номенклатура.Наименование КАК Наименование
|ИЗ
|	Справочник.Номенклатура КАК Номенклатура
|ГДЕ
|	Номенклатура.Ссылка В ИЕРАРХИИ(&Группа)
|	И НЕ Номенклатура.ЭтоГруппа";
Запрос.УстановитьПараметр("Группа", Группа);
Выборка = Запрос.Выполнить().Выбрать();

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

Проверить один элемент запросом

Если нужен ответ «да/нет» для конкретной ссылки, запрос короче:

Запрос = Новый Запрос(
"ВЫБРАТЬ ПЕРВЫЕ 1
|	ИСТИНА КАК Принадлежит
|ИЗ
|	Справочник.Номенклатура КАК Номенклатура
|ГДЕ
|	Номенклатура.Ссылка = &Элемент
|	И Номенклатура.Ссылка В ИЕРАРХИИ(&Группа)");
Запрос.УстановитьПараметр("Элемент", Элемент);
Запрос.УстановитьПараметр("Группа", Группа);
Принадлежит = НЕ Запрос.Выполнить().Пустой();

Несколько групп и проверка в табличных данных

В параметр можно передать массив групп — В ИЕРАРХИИ(&СписокГрупп) проверит все сразу. Оператор работает не только по самому справочнику, но и по реквизиту-ссылке в документах и регистрах:

|ГДЕ
|	ПродажиОбороты.Номенклатура В ИЕРАРХИИ(&СписокГрупп)

Так получают, например, продажи по группе «Бытовая техника» со всеми подгруппами без ручного перечисления.

Проверка в коде: ПринадлежитЭлементу, Родитель и ЭтоГруппа

Во встроенном языке есть три инструмента. Они отвечают на разные вопросы.

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

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

Метод есть у ссылки и у объекта иерархического справочника:

&НаСервере
Функция ВходитВГруппу(Элемент, Группа)
	Если Элемент = Группа Тогда
		Возврат Истина;
	КонецЕсли;
	Возврат Элемент.ПринадлежитЭлементу(Группа);
КонецФункции

Сравнение Элемент = Группа добавлено намеренно. Метод проверяет подчинённость, а вопрос «входит ли группа сама в себя» в разных задачах решают по-разному. Явная проверка убирает неоднозначность и делает поведение функции таким же, как у В ИЕРАРХИИ.

Вызывайте метод на сервере. Он обращается к базе данных, а в управляемой форме на клиенте методы ссылок недоступны. С клиента передайте ссылки в серверную процедуру формы или в общий модуль с флагом «Сервер».

Реквизит Родитель

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

Если Элемент.Родитель = Справочники.Номенклатура.НайтиПоНаименованию("Канцтовары", Истина) Тогда
	// элемент лежит непосредственно в группе «Канцтовары»
КонецЕсли;

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

Признак ЭтоГруппа в форме списка

В форме с динамическим списком тип текущей строки берут из текущих данных, без обращения к базе:

&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
	ТекущиеДанные = Элементы.Список.ТекущиеДанные;
	Если ТекущиеДанные = Неопределено Тогда
		Возврат;
	КонецЕсли;
	Элементы.ФормаЗагрузитьЦены.Доступность = НЕ ТекущиеДанные.ЭтоГруппа;
КонецПроцедуры

Здесь ФормаЗагрузитьЦены — пример имени своей команды на форме, подставьте реальное.

Вложенные уровни: прямой родитель, вся цепочка и глубина

Иногда нужна не проверка «да/нет», а сама структура: на каком уровне лежит элемент, какие группы над ним.

Уровень элемента

Метод Уровень() возвращает номер уровня, верхний уровень — 0.

УровеньЭлемента = Элемент.Уровень();
// 0 — в корне, 1 — внутри одной группы, 2 — в подгруппе и т. д.

Цепочка родителей до корня

Простой цикл по Родитель даёт полный путь:

&НаСервере
Функция ЦепочкаРодителей(Элемент)
	Результат = Новый Массив;
	Текущий = Элемент.Родитель;
	Пока ЗначениеЗаполнено(Текущий) Цикл
		Результат.Вставить(0, Текущий);
		Текущий = Текущий.Родитель;
	КонецЦикла;
	Возврат Результат;
КонецФункции

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

Итоги по иерархии в запросе

Чтобы получить дерево «группа → подгруппы → элементы» с суммами, используют ИТОГИ ... ПО ... ИЕРАРХИЯ:

|ВЫБРАТЬ
|	Остатки.Номенклатура КАК Номенклатура,
|	Остатки.КоличествоОстаток КАК Количество
|ИЗ
|	РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки
|ИТОГИ
|	СУММА(Количество)
|ПО
|	Номенклатура ИЕРАРХИЯ

Результат обходят через Выбрать(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией). Имя регистра в примере условное: в БП, УТ и ERP регистры остатков называются по-разному.

Пустые значения, составные типы и битые ссылки

Проверка принадлежности ломается не на самой иерархии, а на «грязных» входных данных. Вот что стоит проверять до вызова.

  • 🔲 Пустая группа. Если Группа не заполнена, условие теряет смысл. Решите заранее: пустая группа означает «без ограничения» или «ничего не подходит», и обработайте это явно через ЗначениеЗаполнено(Группа).
  • 🔀 Составной тип. Реквизит может хранить ссылки разных справочников или Неопределено. Перед вызовом метода проверьте тип: ТипЗнч(Значение) = Тип("СправочникСсылка.Номенклатура"). Иначе получите ошибку «Метод объекта не обнаружен ».
  • 💔 Битая ссылка. Если элемент удалён непосредственно, в поле видно <Объект не найден>. В конфигурациях на БСП проверяйте ссылку функцией ОбщегоНазначения.СсылкаСуществует(Ссылка).
  • 🗑 Пометка удаления. Помеченные на удаление группы и элементы продолжают участвовать в иерархии. Если их нужно исключить, добавьте НЕ ПометкаУдаления в запрос.
  • 🧭 Другой справочник. Сравнение ссылок разных типов всегда даст Ложь, ошибки не будет — и это хуже, чем ошибка: алгоритм молча «не найдёт» элемент.

Надёжный шаблон функции с защитой от этих случаев:

&НаСервере
Функция ЭлементВГруппе(Значение, Группа)
	Если НЕ ЗначениеЗаполнено(Группа) Тогда
		Возврат Истина; // пустая группа — без ограничения
	КонецЕсли;
	Если ТипЗнч(Значение) <> ТипЗнч(Группа) Тогда
		Возврат Ложь;
	КонецЕсли;
	Если НЕ ЗначениеЗаполнено(Значение) Тогда
		Возврат Ложь;
	КонецЕсли;
	Если Значение = Группа Тогда
		Возврат Истина;
	КонецЕсли;
	Возврат Значение.ПринадлежитЭлементу(Группа);
КонецФункции

Первая ветка — пример бизнес-правила. Если в вашей задаче пустая группа значит «ничего», верните Ложь.

Диагностика: выберите симптом

Какой способ быстрее и когда что выбирать

Скорость зависит не от метода, а от того, сколько раз вы обращаетесь к базе.

СпособОбращений к базеГде уместен
ПринадлежитЭлементу1 на каждый вызовПроверка одного-двух значений: при записи документа, в обработчике формы
Цикл по РодительПо числу уровней на каждый элементПостроение пути для вывода, не для массовых проверок
Запрос с В ИЕРАРХИИ1 на весь наборОтборы, отчёты, массовая обработка
Состав группы в соответствии1 запрос, дальше в памятиМногократные проверки в одном цикле

Пример: обработка проверяет 10 000 строк табличной части. С ПринадлежитЭлементу в цикле это 10 000 серверных обращений. Один запрос даёт тот же ответ за одно обращение.

Если проверять приходится внутри цикла, соберите состав группы заранее:

&НаСервере
Функция СоставГруппы(Группа)
	Запрос = Новый Запрос(
	"ВЫБРАТЬ
	|	Спр.Ссылка КАК Ссылка
	|ИЗ
	|	Справочник.Номенклатура КАК Спр
	|ГДЕ
	|	Спр.Ссылка В ИЕРАРХИИ(&Группа)");
	Запрос.УстановитьПараметр("Группа", Группа);

	Состав = Новый Соответствие;
	Выборка = Запрос.Выполнить().Выбрать();
	Пока Выборка.Следующий() Цикл
		Состав.Вставить(Выборка.Ссылка, Истина);
	КонецЦикла;
	Возврат Состав;
КонецФункции

// В цикле:
Состав = СоставГруппы(Группа);
Для Каждого Строка Из Объект.Товары Цикл
	Если Состав[Строка.Номенклатура] = Истина Тогда
		// строка относится к группе
	КонецЕсли;
КонецЦикла;

Поиск в Соответствии по ключу идёт в памяти и не трогает базу.

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

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

Мини-кейс: скидка на группу товаров

Задача: при записи заказа дать скидку 5% на всё из группы «Расходники», включая подгруппы. В заказе 40 строк.

  • ❌ Неудачно: 40 вызовов ПринадлежитЭлементу, по одному на строку.
  • ✅ Удачно: один запрос с В ИЕРАРХИИ по номенклатуре из табличной части, результат — список строк для скидки.

Код короче, а время записи документа не растёт вместе с числом строк.

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

Входит ли сама группа в результат В ИЕРАРХИИ?
Да. Условие отбирает и саму группу, и всё, что в ней. Уберите её условием Ссылка <> &Группа или НЕ ЭтоГруппа.
Как проверить, что элемент лежит в корне справочника?
Сравните родителя с пустой ссылкой: НЕ ЗначениеЗаполнено(Элемент.Родитель) или Элемент.Уровень() = 0.
Можно ли использовать В ИЕРАРХИИ для документов?
Нет, у документов нет иерархии. Оператор применяют к полю-ссылке на иерархический справочник внутри документа или регистра, например к номенклатуре в табличной части.
Сработает ли проверка, если элемент перенесли в другую группу?
Да. И метод, и запрос смотрят текущее значение Родитель в базе. Старые отчёты пересчитаются по новой структуре, если только они не сохранены готовым результатом.
Как проверить принадлежность сразу к нескольким группам?
Передайте массив групп в параметр: В ИЕРАРХИИ(&СписокГрупп). В отборе отчёта выберите вид сравнения «В группе из списка».