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