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