При разработке отчетов в среде 1С начинающие разработчики часто сталкиваются с необходимостью расширения функционала простых фильтров. Типичная ситуация: отчет отлично работает для одной выбранной организации, но бизнес-задача требует формирования данных сразу по нескольким компаниям. В этой статье мы подробно разберем, как перейти от одиночного выбора к множественному, рассмотрим методы динамического формирования запросов и выясним, почему профессионалы предпочитают использовать Систему компоновки данных (СКД).
Рассмотрим стандартную ситуацию, когда в коде используется прямое сравнение через оператор =. Такой подход позволяет выбрать только одно значение. Для того чтобы база данных поняла, что мы хотим передать целый набор значений, необходимо использовать оператор В (в английской нотации IN). Проанализируем, как должен измениться ваш код.
Вместо передачи одиночной ссылки, мы будем передавать массив или список значений. Давайте изменим исходную функцию, чтобы она поддерживала коллекцию организаций:
// Было:
// Текст = Текст + "Организация = &Организация";
// Запрос.УстановитьПараметр("Организация", Организация);
// Стало:
Если ЗначениеЗаполнено(СписокОрганизаций) Тогда
Текст = Текст + " И Организация В (&СписокОрганизаций)";
Запрос.УстановитьПараметр("СписокОрганизаций", СписокОрганизаций);
КонецЕсли;
Важно помнить, что в параметр &СписокОрганизаций в 1С можно передавать объекты типов Массив, СписокЗначений или даже результат другого запроса. Это делает механизм крайне гибким для разработки.
Когда мы начинаем складывать строки запроса вручную (конкатенация), возникает классическая проблема первого условия. Если у нас несколько фильтров (например, Организация, Склад и Период), и пользователь не выбрал первый фильтр, то текст запроса может начаться со слова И, что приведет к синтаксической ошибке. Рассмотрим, как решить эту задачу изящно.
Способ 1: Массив условий. Мы создаем массив строк, в который добавляем условия только тогда, когда параметры заполнены. Затем соединяем их через «И».
МассивУсловий = Новый Массив;
Если ЗначениеЗаполнено(Организация) Тогда
МассивУсловий.Добавить("Организация В (&СписокОрганизаций)");
Запрос.УстановитьПараметр("СписокОрганизаций", СписокОрганизаций);
КонецЕсли;
Если ЗначениеЗаполнено(Склад) Тогда
МассивУсловий.Добавить("Склад = &Склад");
Запрос.УстановитьПараметр("Склад", Склад);
КонецЕсли;
Если МассивУсловий.Количество() > 0 Тогда
ТекстЗапроса = ТекстЗапроса + " ГДЕ " + СтрСоединить(МассивУсловий, " И ");
КонецЕсли;
Способ 2: Трюк «ГДЕ ИСТИНА». Разберем еще один популярный метод. Мы сразу пишем в запросе ГДЕ ИСТИНА (или ГДЕ 1=1), а все последующие условия просто добавляем через И. Это избавляет от необходимости проверять, является ли текущее условие первым.
Текст = "ВЫБРАТЬ * ИЗ Документ.РеализацияТоваровУслуг КАК Реализация ГДЕ ИСТИНА";
Если ЗначениеЗаполнено(Организация) Тогда
Текст = Текст + " И Реализация.Организация В (&СписокОрганизаций)";
Запрос.УстановитьПараметр("СписокОрганизаций", СписокОрганизаций);
КонецЕсли;
Проанализируем важный нюанс: что произойдет, если передать в запрос пустой Массив или СписокЗначений? В 1С оператор В при пустом списке вернет «Ложь» для каждой строки. Это значит, что отчет будет пустым. В отличие от некоторых других систем, 1С не игнорирует пустой фильтр автоматически. Поэтому всегда проверяйте заполненность списка перед тем, как добавлять условие в текст запроса. Если список пуст — значит, пользователь хочет видеть данные по всем организациям, и условие добавлять не нужно.
Для разработчиков, пришедших из C#, ручная склейка строк может казаться привычной, но в 1С существует мощный декларативный инструмент — СКД. Посмотрим, почему стоит переходить на него как можно скорее:
Если ЗначениеЗаполнено.... Система сама проанализирует, какие отборы установил пользователь на форме, и динамически изменит текст SQL-запроса.РегистрНакопления.Продажи.Обороты(,,,&Организация)). Это работает в разы быстрее, чем фильтрация через ГДЕ.Выясним причину, по которой работа в 1С поначалу кажется неудобной. В 1С нет прямого аналога LINQ, который позволяет строить запросы объектно. Однако, если вам необходимо программно манипулировать структурой запроса, обратите внимание на объект СхемаЗапроса. Он позволяет обращаться к частям запроса (выбираемым полям, источникам, условиям) как к коллекции объектов, что гораздо безопаснее конкатенации строк.
Также рекомендуем использовать специализированные инструменты для отладки — Консоль запросов и Консоль СКД. Они позволяют быстро проверить работу фильтров с разными наборами данных без перезапуска всей программы. Это значительно экономит время при поиске ошибок в логике условий.
При использовании фильтров по нескольким организациям в больших базах данных важно убедиться, что поле Организация проиндексировано. В типовых конфигурациях это обычно так, но если вы создаете собственные документы или регистры, не забудьте установить свойство «Индексировать». Это позволит СУБД быстро находить нужные записи, даже если в списке передано несколько десятков организаций.
Подведем итог: для простых задач достаточно использовать оператор В и массив параметров, но для создания надежных и масштабируемых отчетов лучше освоить СКД. Это сэкономит время на обработку пустых значений и обеспечит пользователям максимальную гибкость в настройке фильтров.