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