Как в 1С получить элементы текущей папки справочника через запрос?

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

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

Постановка задачи и базовый запрос

Предположим, у нас есть иерархический справочник Номенклатура. Нам нужно получить все элементы, которые находятся внутри определенной папки. Для начала разберем структуру базового запроса. Чтобы ограничить выборку конкретной папкой, в языке запросов 1С используется предложение ГДЕ.

Проанализируем пример кода, который выбирает ссылку и код номенклатуры:


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

В данном примере мы используем параметр &ТекущаяПапка. Если мы просто выполним этот запрос без установки значения параметра, система выдаст ошибку: "Не задано значение параметра". Поэтому крайне важно перед выполнением метода Запрос.Выполнить() передать в него конкретную ссылку на папку справочника.

Как программно определить текущую папку в форме

Самый важный вопрос — как получить ссылку на ту папку, в которой сейчас находится пользователь в интерфейсе? Решение зависит от типа приложения (Обычное или Управляемое), но принцип остается схожим.

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


// Получаем родителя из табличного поля "СправочникСписок"
ПапкаДляФильтра = ЭлементыФормы.СправочникСписок.ТекущийРодитель;

// Устанавливаем параметр в запрос
Запрос.УстановитьПараметр("ТекущаяПапка", ПапкаДляФильтра);

В управляемых формах (современный интерфейс) обращение будет выглядеть несколько иначе. Мы обращаемся к динамическому списку, который обычно называется Список:


// Для управляемых форм
ПапкаДляФильтра = Элементы.Список.ТекущийРодитель;
Запрос.УстановитьПараметр("ТекущаяПапка", ПапкаДляФильтра);

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

Выбор между операторами «Родитель =» и «В ИЕРАРХИИ»

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

  1. Условие Родитель = &ТекущаяПапка: Выбирает элементы, которые находятся СТРОГО внутри указанной папки. Вложенные подпапки и их содержимое в выборку не попадут. Это работает максимально быстро.
  2. Условие Ссылка В ИЕРАРХИИ(&ТекущаяПапка): Выберет саму папку, все её элементы, а также все элементы во всех вложенных папках на любую глубину. Это полезно, если вы хотите сделать "сквозной" фильтр по всей ветке справочника.

Пример использования иерархического условия:


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

Реализация динамического фильтра по реквизиту

Рассмотрим ситуацию, упомянутую в обсуждении: нам нужно получить список уникальных цветов (реквизит Цвет), которые есть у товаров в текущей папке. Для этого мы добавим ключевое слово РАЗЛИЧНЫЕ. Это позволит избежать дублей в итоговом списке фильтра.

Проанализируем комплексный пример кода:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ РАЗЛИЧНЫЕ
    |	Номенклатура.Цвет КАК Цвет
    |ИЗ
    |	Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |	Номенклатура.Родитель = &ТекущаяПапка 
    |	И НЕ Номенклатура.ЭтоГруппа"; // Выбираем только элементы, не папки

Запрос.УстановитьПараметр("ТекущаяПапка", ЭлементыФормы.СправочникСписок.ТекущийРодитель);

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

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

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

Автоматизация обновления при смене папки

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

В управляемом приложении для динамического списка рекомендуется использовать программную установку отбора в объекте КомпоновщикНастроек, если ваша цель — просто отфильтровать сам список. Но если данные нужны для сторонних нужд (вывод в консоль или заполнение вспомогательного списка), использование ручного запроса, как мы разобрали выше, является оптимальным решением.

Рекомендации по производительности

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

← На главную