Как выбрать все подчиненные элементы иерархического справочника произвольной вложенности в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При работе с иерархическими справочниками в платформе 1С:Предприятие часто возникает задача получить полный список всех подчиненных элементов для определенного узла на всю глубину вложенности. Например, если узел А1 содержит узел А3, а тот в свою очередь содержит элемент А31, требуется получить как прямых потомков (А2, А3), так и вложенных (А31).

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

Почему стандартный метод Выбрать() не обходит вложенные уровни

Рассмотрим стандартный вызов объектной выборки:


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

В данном сценарии метод Выбрать(Родитель) возвращает только те элементы и группы, которые непосредственно подчинены переданному родителю. То есть выборка ограничивается ровно одним уровнем вложенности вниз. Вложенные папки и их содержимое при таком подходе автоматически не разворачиваются.

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

Способ 1. Запрос с конструкцией В ИЕРАРХИИ (рекомендуемый способ)

Наиболее эффективным, быстрым и надежным способом получения всех подчиненных элементов любой глубины является использование языка запросов 1С с оператором В ИЕРАРХИИ. Вся работа по рекурсивному обходу дерева в этом случае выполняется средствами СУБД.

Разберем пример запроса для получения плоского списка всех вложенных элементов:


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

Запрос.УстановитьПараметр("Родитель", Под);

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

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

Способ 2. Построение дерева с помощью ИТОГИ ПО Ссылка ИЕРАРХИЯ

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


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

Запрос.УстановитьПараметр("Родитель", Под);

Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией);

Пока Выборка.Следующий() Цикл
    Сообщить(Выборка.Наименование);
КонецЦикла;

Способ 3. Использование метода ВыбратьИерархически()

Если по условиям задачи необходимо использовать объектную модель без обращения к запросам, применим метод менеджера справочника ВыбратьИерархически(). Главная особенность заключается в правильном методе обхода:

  1. Метод Выборка.Следующий() перемещается только по элементам текущего уровня.
  2. Метод Выборка.ПолучитьСледующегоПоИерархии() осуществляет сквозной проход по всему дереву сверху вниз с заходом во все вложенные папки.

Посмотрим на пример кода с правильным обходом:


Выборка = Справочники.Номенклатура.ВыбратьИерархически(Под);
Пока Выборка.ПолучитьСледующегоПоИерархии() Цикл
    Сообщить(Выборка.Ссылка);
КонецЦикла;

Проверка настроек метаданных справочника

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

  1. Иерархия групп и элементов: в этом режиме родителями могут выступать исключительно группы (папки). Если узел А3 создан как обычный элемент (а не группа), подчинить ему элемент А31 в пользовательском интерфейсе невозможно, и подчиненности в базе не возникнет.
  2. Иерархия элементов: в этом режиме любой элемент справочника может выступать родителем для другого элемента. Если требуется вкладывать элементы друг в друга без использования папок, в свойствах справочника должен быть установлен именно этот вид иерархии.
← На главную