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

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

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

Разбор проблемы: почему не работает поиск по нескольким кодам сразу

Метод Справочники.<ИмяСправочника>.НайтиПоКоду() ищет в базе строго одну запись, код которой в точности совпадает со строковым параметром. Передача выражения вида "000000002 + 000000001" воспринимается платформой как попытка найти элемент с таким экзотическим кодом, что возвращает пустую ссылку.

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

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

Шаг 1. Корректировка текста запроса

Проанализируем условие отбора в секции ГДЕ. Когда отбор строится по одиночному значению, используется оператор =:


ГДЕ
    РеализацияТоваровУслуг.ВидОплаты = &ВидОплаты

Для работы с несколькими элементами заменим условие на проверку вхождения в список параметров с помощью оператора В:


ГДЕ
    РеализацияТоваровУслуг.ВидОплаты В (&СписокВидовОплаты)
    И РеализацияТоваровУслуг.Дата МЕЖДУ &НачПериода И &КонПериода
    И РеализацияТоваровУслуг.Проведен = ИСТИНА

Шаг 2. Формирование коллекции значений для параметра

Теперь соберем коллекцию элементов, которые будут переданы в параметр запроса &СписокВидовОплаты. Для этого можно использовать Массив или СписокЗначений. Если выбран режим отбора по двум видам оплаты одновременно, наполняем коллекцию найденными ссылками:


МассивВидовОплаты = Новый Массив;
МассивВидовОплаты.Добавить(Справочники.ВидыОплатыТЧ.НайтиПоКоду("000000001"));
МассивВидовОплаты.Добавить(Справочники.ВидыОплатыТЧ.НайтиПоКоду("000000002"));

Запрос.УстановитьПараметр("СписокВидовОплаты", МассивВидовОплаты);

Если требуется отобрать только один вид оплаты, в массив помещается лишь один элемент — запрос с конструкцией В (&СписокВидовОплаты) корректно обработает коллекцию любого размера.

Шаг 3. Устранение ошибки «Метод объекта не обнаружен (Добавить)»

При реализации данного кода разработчики нередко сталкиваются с исключением:

{Обработка.ПроверкаОплаты.Форма.Отчет(119)}: Метод объекта не обнаружен (Добавить)

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

Чтобы избежать подобных коллизий, используем следующие правила:

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

Альтернативные и более надежные способы реализации

Использование метода НайтиПоКоду в коде конфигурации несет определенные риски: метод чувствителен к длине строки, ведущим нулям и уникальности кодов при ручном редактировании. Разберем альтернативные архитектурные решения:

  1. Предопределенные элементы: если виды оплаты зафиксированы в логике учета, их следует создать как предопределенные элементы справочника. В тексте запроса к ним можно обращаться напрямую без параметров через конструкцию ЗНАЧЕНИЕ(Справочник.ВидыОплатыТЧ.ИмяЭлемента), либо передавать через метод ПредопределенноеЗначение().
  2. Фильтрация по коду непосредственно в запросе: можно передать в запрос массив строковых кодов и проверить поле через точку:
    
    ГДЕ
        РеализацияТоваровУслуг.ВидОплаты.Код В (&МассивКодов)
    
    Обратите внимание: обращение через точку к реквизиту справочника создает неявное соединение таблиц на уровне СУБД.
  3. Использование типа «Массив» вместо «СписокЗначений»: для передачи параметров в запрос предпочтительнее использовать Массив, так как он расходует меньше оперативной памяти и не хранит вспомогательные метаданные (пометки, представления, картинки).
  4. Обработка пустой коллекции: важно помнить, что если в параметр передается пустой массив (0 элементов), условие В (&СписокВидовОплаты) вернет Ложь, и в результат запроса не попадет ни одна запись.
← На главную