Как динамически подставлять справочник в запрос 1С и эффективно фильтровать данные?

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

В процессе разработки часто возникает задача, когда необходимо выполнить запрос к разным справочникам в зависимости от выбора пользователя на форме. Попытки передать Таблицу Значений ТЗ с типом справочника в качестве параметра запроса часто приводят к ошибкам вида «Поле не найдено» или проблемам с производительностью. Давайте разберем, почему так происходит и как реализовать это правильно.

Почему не стоит передавать Таблицу Значений в запрос

Когда мы пытаемся передать ТЗ в запрос как источник данных, 1С воспринимает её как временный набор строк, лишенный метаданных. В результате при попытке обратиться к полям объекта через точку, например Статьи.Родитель.Код, система не может выполнить разыменование, так как в ТЗ хранятся лишь ссылки, а не структура метаданных. Кроме того, такой подход принуждает платформу выполнять неявные соединения с таблицами базы данных, что ведет к катастрофическому падению производительности и полному сканированию таблиц (Table Scan).

Решение 1: Динамическая замена текста запроса

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

Допустим, на форме есть список выбора с именами справочников. Мы можем использовать следующий алгоритм:


// Предположим, ВидСправочника содержит строку "СтатьиЗатрат"
ИмяСправочника = ЭтаФорма.ВидСправочника; 
Родитель = Справочники[ИмяСправочника].НайтиПоКоду("БП-000001");

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

// Заменяем шаблонное имя на выбранное пользователем
Запрос.Текст = СтрЗаменить(Запрос.Текст, "ШаблонСправочника", ИмяСправочника);
Запрос.УстановитьПараметр("Родитель", Родитель);
Результат = Запрос.Выполнить().Выгрузить();

Этот метод позволяет оптимизатору СУБД корректно построить план выполнения запроса, используя существующие индексы, что обеспечивает высокую скорость работы даже на больших объемах данных.

Решение 2: Использование иерархических выборок

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

Для доступа к менеджерам справочников динамически мы используем конструкцию Справочники[ИмяСправочника]. Это избавляет нас от необходимости создавать лишние объекты в памяти и позволяет сразу получить ссылку на нужный элемент для передачи в параметр &Родитель.

Рекомендации по реализации на форме

  1. Выведите на форму текстовое поле или список выбора, в котором пользователь будет указывать, с каким справочником он хочет работать.
  2. Для списка выбора задайте значения, которые соответствуют именам справочников в конфигураторе (например, СтатьиЗатрат, СтатьиДвиженияДенежныхСредств).
  3. При выполнении кода считывайте выбранное значение и используйте его как ключ для доступа к менеджеру справочника (Справочники[ИмяСправочника]).
  4. Используйте метод СтрЗаменить для подготовки текста запроса, чтобы не нарушать структуру SQL-команд.

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

← На главную