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