Почему не срабатывает событие ОбработкаВыбора при открытии формы выбора в 1С?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

При программном вызове форм выбора разработчики часто сталкиваются с ситуацией, когда после интерактивного выбора значения пользователем стандартное событие формы-источника ОбработкаВыбора не срабатывает. В результате выбранное значение не попадает в табличную часть или реквизит документа. Рассмотрим подробно причины такого поведения платформы 1С, выясним, как правильно связать открываемую форму выбора с формой-владельцем, и разберем типовые сценарии фильтрации данных.

Анализ проблемы: почему форма выбора теряет связь с вызывающей формой

Для автоматической передачи выбранного значения платформа 1С должна знать получателя этого значения — владельца формы. В методе ПолучитьФормуВыбора() вторым параметром передается владелец (это может быть сама форма — ЭтаФорма, либо конкретный элемент управления, например, ЭлементыФормы.Контрагент).

Если при получении формы параметр владельца опущен, например:


ФормаКонтр = Справочники.Контрагенты.ПолучитьФормуВыбора("ФормаВыбора");
ФормаКонтр.Открыть();

то открытая форма выбора не имеет связи с вызывающим окном. При нажатии кнопки «Выбрать» или двойном клике платформа просто закроет окно выбора и не отправит оповещение в процедуру ОбработкаВыбора.

Решение 1: Указание владельца формы при программном открытии

Разберем, как исправить вызов. Если нам требуется обработать выбор самостоятельно в процедуре ОбработкаВыбора (например, при множественном подборе товаров или выполнении сложной логики проверки), передаем текущую форму (ЭтаФорма) в качестве владельца:


Процедура ПодборТовараНажатие(Элемент)

    Если ЭлементыФормы.Склад.Значение.Пустая() Тогда
        Предупреждение("Вы не выбрали склад!");
        Возврат;
    КонецЕсли;

    // Вторым параметром явно передаем ЭтаФорма
    ФормаПодбора = Справочники.Номенклатура.ПолучитьФормуВыбора("ФормаВыбора", ЭтаФорма); 
    ФормаПодбора.ЗакрыватьПриВыборе = Ложь;
    ФормаПодбора.Заголовок = "Подбор продажи";
    ФормаПодбора.Открыть();

КонецПроцедуры

Теперь при выборе любого элемента в открытом окне платформа будет вызывать процедуру-событие ОбработкаВыбора в контексте формы документа.

Решение 2: Обработка результата при модальном открытии

Если форма открывается модально с помощью метода ОткрытьМодально(), использовать событие ОбработкаВыбора не требуется. Метод ОткрытьМодально() сам возвращает выбранное значение непосредственно в точку вызова. Посмотрим на пример реализации:


ФормаКонтр = Справочники.Контрагенты.ПолучитьФормуВыбора("ФормаВыбора");
// Настраиваем отбор
ФормаКонтр.Отбор.Родитель.ВидСравнения = ВидСравнения.Равно;
ФормаКонтр.Отбор.Родитель.Значение = ВыбранныйРодитель;
ФормаКонтр.Отбор.Родитель.Использование = Истина;

// Получаем результат напрямую
ВыбранноеЗначение = ФормаКонтр.ОткрытьМодально();

Если ЗначениеЗаполнено(ВыбранноеЗначение) Тогда
    ЭлементыФормы.Мастер.Значение = ВыбранноеЗначение;
КонецЕсли;

Решение 3: Использование стандартного события НачалоВыбора

В типовых конфигурациях 1С ручное открытие через кнопки подбора часто заменяют или дополняют переопределением стандартного события элемента управления НачалоВыбора. В этом случае отпадает необходимость вручную обрабатывать возврат в ОбработкаВыбора — платформа сама запишет результат в реквизит, если в качестве владельца формы выбора передан ЭлементФормы.

Разберем по шагам, как это реализовано в типовых решениях:

  1. Отключаем стандартную обработку выбора, установив параметр СтандартнаяОбработка = Ложь.
  2. Получаем форму выбора, передав элемент формы в качестве владельца.
  3. Устанавливаем необходимые фильтры через коллекцию Отбор.
  4. Открываем форму.

Посмотрим на пример кода процедуры:


Процедура ДоговорКонтрагентаНачалоВыбора(Элемент, СтандартнаяОбработка)

    СтандартнаяОбработка = Ложь;

    // Передаем Элемент в качестве владельца формы выбора
    ФормаВыбора = Справочники.ДоговорыКонтрагентов.ПолучитьФормуВыбора(, Элемент);

    // Устанавливаем фильтрацию по владельцу (Контрагенту)
    ФормаВыбора.ПараметрОтборПоВладельцу = Контрагент;
    ФормаВыбора.ЭлементыФормы.СправочникСписок.НастройкаОтбора.Владелец.Доступность = Ложь;

    // Устанавливаем отбор по видам договоров
    СписокВидов = Новый СписокЗначений;
    СписокВидов.Добавить(Перечисления.ВидыДоговоровКонтрагентов.СПокупателем);
    СписокВидов.Добавить(Перечисления.ВидыДоговоровКонтрагентов.СКомиссионером);

    ФормаВыбора.СправочникСписок.Отбор.ВидДоговора.ВидСравнения = ВидСравнения.ВСписке;
    ФормаВыбора.СправочникСписок.Отбор.ВидДоговора.Значение = СписокВидов;
    ФормаВыбора.СправочникСписок.Отбор.ВидДоговора.Использование = Истина;
    ФормаВыбора.ЭлементыФормы.СправочникСписок.НастройкаОтбора.ВидДоговора.Доступность = Ложь;

    ФормаВыбора.ПараметрВыборГруппИЭлементов = ИспользованиеГруппИЭлементов.Элементы;
    ФормаВыбора.НачальноеЗначениеВыбора = ДоговорКонтрагента;

    ФормаВыбора.Открыть();

КонецПроцедуры

Рекомендации по оптимизации и идентификации выбора

Проанализируем дополнительные важные нюансы при работе с формами выбора:

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