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