Как реализовать выбор нескольких организаций в фильтре отчета 1С?

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

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

Переход к оператору «В» для множественного выбора

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

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


// Было:
// Текст = Текст + "Организация = &Организация";
// Запрос.УстановитьПараметр("Организация", Организация);

// Стало:
Если ЗначениеЗаполнено(СписокОрганизаций) Тогда
    Текст = Текст + " И Организация В (&СписокОрганизаций)";
    Запрос.УстановитьПараметр("СписокОрганизаций", СписокОрганизаций);
КонецЕсли;

Важно помнить, что в параметр &СписокОрганизаций в 1С можно передавать объекты типов Массив, СписокЗначений или даже результат другого запроса. Это делает механизм крайне гибким для разработки.

Динамическое формирование текста запроса: избегаем ошибок

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

Способ 1: Массив условий. Мы создаем массив строк, в который добавляем условия только тогда, когда параметры заполнены. Затем соединяем их через «И».


МассивУсловий = Новый Массив;
Если ЗначениеЗаполнено(Организация) Тогда
    МассивУсловий.Добавить("Организация В (&СписокОрганизаций)");
    Запрос.УстановитьПараметр("СписокОрганизаций", СписокОрганизаций);
КонецЕсли;

Если ЗначениеЗаполнено(Склад) Тогда
    МассивУсловий.Добавить("Склад = &Склад");
    Запрос.УстановитьПараметр("Склад", Склад);
КонецЕсли;

Если МассивУсловий.Количество() > 0 Тогда
    ТекстЗапроса = ТекстЗапроса + " ГДЕ " + СтрСоединить(МассивУсловий, " И ");
КонецЕсли;

Способ 2: Трюк «ГДЕ ИСТИНА». Разберем еще один популярный метод. Мы сразу пишем в запросе ГДЕ ИСТИНА (или ГДЕ 1=1), а все последующие условия просто добавляем через И. Это избавляет от необходимости проверять, является ли текущее условие первым.


Текст = "ВЫБРАТЬ * ИЗ Документ.РеализацияТоваровУслуг КАК Реализация ГДЕ ИСТИНА";
Если ЗначениеЗаполнено(Организация) Тогда
    Текст = Текст + " И Реализация.Организация В (&СписокОрганизаций)";
    Запрос.УстановитьПараметр("СписокОрганизаций", СписокОрганизаций);
КонецЕсли;

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

Проанализируем важный нюанс: что произойдет, если передать в запрос пустой Массив или СписокЗначений? В 1С оператор В при пустом списке вернет «Ложь» для каждой строки. Это значит, что отчет будет пустым. В отличие от некоторых других систем, 1С не игнорирует пустой фильтр автоматически. Поэтому всегда проверяйте заполненность списка перед тем, как добавлять условие в текст запроса. Если список пуст — значит, пользователь хочет видеть данные по всем организациям, и условие добавлять не нужно.

Система компоновки данных (СКД) — профессиональный подход

Для разработчиков, пришедших из C#, ручная склейка строк может казаться привычной, но в 1С существует мощный декларативный инструмент — СКД. Посмотрим, почему стоит переходить на него как можно скорее:

  1. Автоматизация фильтров: Вам не нужно писать Если ЗначениеЗаполнено.... Система сама проанализирует, какие отборы установил пользователь на форме, и динамически изменит текст SQL-запроса.
  2. Виртуальные таблицы: При работе с остатками и оборотами крайне важно передавать фильтры в параметры виртуальных таблиц (например, РегистрНакопления.Продажи.Обороты(,,,&Организация)). Это работает в разы быстрее, чем фильтрация через ГДЕ.
  3. Гибкость интерфейса: Пользователь сможет самостоятельно выбирать вид сравнения: «Равно», «В списке», «Не в списке» или «Заполнено», не меняя ни строчки вашего кода.

Советы для разработчиков, переходящих с C#

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

Также рекомендуем использовать специализированные инструменты для отладки — Консоль запросов и Консоль СКД. Они позволяют быстро проверить работу фильтров с разными наборами данных без перезапуска всей программы. Это значительно экономит время при поиске ошибок в логике условий.

Производительность и индексация

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

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

← На главную