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