Как выбрать все папки, входящие в определенную группу справочника 1С

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

При работе со справочниками в системе «1С:Предприятие 8» часто возникает задача программного получения списка элементов или групп, которые находятся внутри определенного родителя. Это может быть необходимо для построения отчетов, обработки номенклатуры или автоматического заполнения документов. В этой статье мы подробно разберем, как эффективно решать подобные задачи, используя различные механизмы платформы.

Метод 1: Использование запроса с оператором В ИЕРАРХИИ

Использование запросов — это наиболее правильный и производительный способ получения данных в 1С. Для того чтобы выбрать все подчиненные группы внутри конкретной папки (например, «Торговая деятельность»), нам потребуется использовать условие В ИЕРАРХИИ. Рассмотрим, чем оно отличается от обычного сравнения.

Анализируем разницу в условиях:

  1. Условие ГДЕ Родитель = &Параметр выберет только тех «потомков», которые находятся на первом уровне вложенности относительно родителя.
  2. Условие ГДЕ Ссылка В ИЕРАРХИИ(&Параметр) выберет все элементы и группы на всех уровнях вложенности, фактически «спускаясь» до самого низа дерева справочника.

Разберем пример кода, который выбирает только группы (папки) внутри заданной иерархии:


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

// Сначала найдем ссылку на нашу группу «Торговая деятельность»
ГруппаСсылка = Справочники.Номенклатура.НайтиПоНаименованию("Торговая деятельность");

// Устанавливаем параметр запроса
Запрос.УстановитьПараметр("РодительскаяГруппа", ГруппаСсылка);

РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

Пока Выборка.Следующий() Цикл
    // Здесь выполняем действия с найденной группой
    Сообщить("Найдена группа: " + Выборка.Ссылка);
КонецЦикла;

Важный нюанс: Обратите внимание на свойство ЭтоГруппа. Оно позволяет отсеять конечные элементы (товары) и оставить только папки. Если вам нужны и папки, и товары, это условие можно просто убрать.

Метод 2: Объектная техника с использованием метода Выбрать()

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

Синтаксис метода следующий: Выбрать(<Родитель>, <Владелец>, <Отбор>, <Порядок>). Если мы передаем в первый параметр ссылку на конкретную группу, система вернет выборку элементов, находящихся непосредственно в ней.


Родитель = Справочники.Номенклатура.НайтиПоНаименованию("Торговая деятельность");
Выборка = Справочники.Номенклатура.Выбрать(Родитель);

Пока Выборка.Следующий() Цикл
    Если Выборка.ЭтоГруппа Тогда
        Сообщить("Найдена вложенная папка: " + Выборка.Наименование);
    КонецЕсли;
КонецЦикла;

Проанализируем ограничение этого метода: он не работает рекурсивно. То есть, если внутри папки «Торговая деятельность» есть папка «Часы», а внутри «Часов» есть еще папки, метод Выбрать() вернет только папку «Часы». Чтобы получить всю глубину вложенности без запроса, пришлось бы писать рекурсивную функцию, что крайне не рекомендуется из-за низкой производительности.

Особенности поиска родительской группы

В примерах выше мы использовали метод НайтиПоНаименованию(). Рассмотрим, почему это может быть опасно в реальных задачах:

  1. Дублирование названий: В справочнике может быть две папки с именем «Товары» в разных ветках. Система вернет первую попавшуюся.
  2. Человеческий фактор: Если пользователь переименует папку в интерфейсе, ваш программный код перестанет находить группу.

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

Типичная ошибка: Сброс родителя при использовании ЗаполнитьЗначенияСвойств

Проанализируем ситуацию, когда нам нужно программно создать новый элемент в определенной папке, скопировав данные из другого объекта. Часто программисты сталкиваются с тем, что элемент упорно записывается в корень справочника, несмотря на установку родителя.

Рассмотрим ошибочный порядок действий:


НовыйТовар = Справочники.Номенклатура.СоздатьЭлемент();
НовыйТовар.Родитель = НужнаяГруппа; // Установили родителя
ЗаполнитьЗначенияСвойств(НовыйТовар, ОбъектИсточник); // ОШИБКА: Родитель затерся!
НовыйТовар.Записать();

Выясним причину проблемы: Метод ЗаполнитьЗначенияСвойств копирует все совпадающие по имени поля. Если в ОбъектИсточник поле Родитель пустое (корень), то оно перезапишет ваше значение.

Правильное решение: Всегда устанавливайте специфические реквизиты (Родитель, Владелец) после массового заполнения свойств.


НовыйТовар = Справочники.Номенклатура.СоздатьЭлемент();
// Сначала заполняем общие реквизиты (наименование, артикул и т.д.)
ЗаполнитьЗначенияСвойств(НовыйТовар, ОбъектИсточник); 

// Затем принудительно устанавливаем правильное место в иерархии
НовыйТовар.Родитель = Справочники.Номенклатура.НайтиПоКоду("00001");
НовыйТовар.Записать();

Дополнительные инструменты: ПринадлежитЭлементу()

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

Пример использования:


Если ОбъектНоменклатура.Ссылка.ПринадлежитЭлементу(ГруппаТорговля) Тогда
    Сообщить("Этот товар относится к торговой деятельности");
КонецЕсли;

Подводя итог, для массового выбора иерархических данных всегда отдавайте предпочтение запросам с оператором В ИЕРАРХИИ. Это обеспечит стабильную работу системы даже при больших объемах данных и сложной структуре папок.

← На главную