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