Почему не работает процедура ОбработкаВыбора при подборе и как это исправить?

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

В процессе разработки в среде «1С:Предприятие 8» программисты часто сталкиваются с ситуацией, когда программно вызванная форма выбора справочника или другого объекта не возвращает выбранное значение в вызывающую форму. Чаще всего эта проблема проявляется в конфигурациях на обычных формах, таких как УПП 1.3 или ЗУП 2.5. Рассмотрим подробно, почему это происходит, разберем механизм взаимодействия форм и научимся правильно реализовывать множественный подбор в табличную часть.

Выясняем причину: почему событие ОбработкаВыбора «молчит»

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

В системе 1С существует жесткая иерархия взаимодействия объектов. Когда одна форма открывает другую для выбора значения, она должна «представиться» в качестве владельца. Если владелец не указан, форма выбора открывается автономно. Она позволяет выбрать элемент, но после выбора система не знает, кому отправить результат, и событие ОбработкаВыбора просто не инициируется.

Посмотрим на ошибочный фрагмент кода:


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

Разберем по шагам, как исправить эту логику и заставить систему работать правильно.

Решение №1: Явное указание владельца формы

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

Если вы хотите, чтобы выбор обрабатывался на уровне всей формы, владельцем нужно указать ЭтаФорма. Если же выбор идет в конкретное табличное поле, лучше указать в качестве владельца именно элемент управления (табличное поле).

Исправленный код вызова формы подбора будет выглядеть так:


Процедура ОткрытьФормуВыбораФЛ(ВладелецФормы, Ключ, ЗакрыватьПриВыборе) Экспорт
    
    // Получаем форму выбора, передавая Владельца (первый параметр)
    ФормаВыбора = Справочники.ФизическиеЛица.ПолучитьФормуВыбора("ФормаВыбора", ВладелецФормы);
    
    // Настраиваем режим множественного подбора
    ФормаВыбора.МножественныйВыбор = Истина;
    ФормаВыбора.ЗакрыватьПриВыборе = Ложь;
    
    ФормаВыбора.Заголовок = "Выберите Физических лиц для заполнения:";
    ФормаВыбора.Открыть();
    
КонецПроцедуры

В этом случае, когда пользователь нажмет кнопку «Выбрать» в справочнике, система автоматически найдет процедуру ОбработкаВыбора у объекта, переданного в ВладелецФормы.

Решение №2: Реализация множественного подбора через ОбработкаВыбора

Когда мы реализуем подбор (когда форма выбора не закрывается после каждого клика), процедура ОбработкаВыбора должна быть готова к приему данных. Если включено свойство МножественныйВыбор, то в параметр ВыбранноеЗначение может прийти как одиночная ссылка, так и целый массив ссылок (если выбор был сделан группой).

Проанализируем правильную структуру обработчика в форме документа. Важно установить СтандартнаяОбработка = Ложь, чтобы система не пыталась вставить значение стандартным способом в текущую ячейку, так как мы планируем программно добавлять новые строки.

Пример правильной обработки выбора:


Процедура ДопДниБольничныхОтпусковСотрудниковОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь; // Отключаем стандартный механизм
    
    // Проверяем, что нам вернули массив или одиночное значение
    Если ТипЗнч(ВыбранноеЗначение) = Тип("Массив") Тогда
        МассивФизЛиц = ВыбранноеЗначение;
    Иначе
        МассивФизЛиц = Новый Массив;
        МассивФизЛиц.Добавить(ВыбранноеЗначение);
    КонецЕсли;
    
    // Обрабатываем каждое выбранное физическое лицо
    Для Каждого ФизЛицоСсылка Из МассивФизЛиц Цикл
        
        Если ТипЗнч(ФизЛицоСсылка) <> Тип("СправочникСсылка.ФизическиеЛица") Тогда
            Продолжить;
        КонецЕсли;
        
        // Проверяем, нет ли уже такого человека в таблице
        ПараметрыПоиска = Новый Структура("ФизЛицо", ФизЛицоСсылка);
        НайденныеСтроки = ДопДниБольничныхОтпусковСотрудников.НайтиСтроки(ПараметрыПоиска);
        
        Если НайденныеСтроки.Количество() = 0 Тогда
            // Добавляем новую строку и заполняем данные
            НоваяСтрока = ДопДниБольничныхОтпусковСотрудников.Добавить();
            НоваяСтрока.ФизЛицо = ФизЛицоСсылка;
            
            // Здесь вызываем логику расчета дополнительных дней
            ЗаполнитьДанныеПоСотруднику(НоваяСтрока);
        КонецЕсли;
        
    КонецЦикла;
    
КонецПроцедуры

Оптимизация: Работа с запросами и производительность

В исходном примере кода автора была допущена еще одна критическая ошибка: выполнение запроса внутри цикла Пока Выборка.Следующий(). Если пользователь выберет 50 или 100 физических лиц, система выполнит 100 отдельных запросов к базе данных, что приведет к значительным задержкам.

Рассмотрим, как оптимизировать этот процесс. Проанализируем ситуацию: нам нужно получить данные о стаже для всех выбранных лиц. Правильнее будет сначала собрать все выбранные ссылки в массив, а затем выполнить один запрос ко всем сотрудникам сразу.

Рекомендуемый подход к заполнению данных:

  1. Собрать все ФизЛицоСсылка из подбора в массив.
  2. Передать этот массив в запрос как параметр ГДЕ Физлицо В (&МассивФизЛиц).
  3. Выгрузить результат запроса в таблицу значений или сразу обходить его для заполнения ТЧ документа.

Также обратим внимание на использование методов НайтиПоКоду и НайтиПоНаименованию внутри обработчиков. Это считается «плохим тоном» в разработке 1С (хардкод), так как при изменении кода или названия в справочнике программа перестанет работать. Проанализируем альтернативу: лучше использовать предопределенные элементы (если конфигурация позволяет) или выносить настройки в константы или дополнительные реквизиты.

Использование механизма ОповеститьОВыборе

Если по каким-то причинам стандартная связь через владельца не подходит (например, форма выбора открывается из сложной цепочки вспомогательных окон), можно использовать альтернативный метод — оповещение. В этом случае в форме выбора справочника в обработчике нажатия кнопки выбора пишется:

ОповеститьОВыборе(ВыбранныйЭлемент);

Этот метод принудительно посылает сигнал владельцу формы. Но важно помнить: чтобы этот сигнал был принят, владелец все равно должен быть указан при открытии.

Подведем итоги. Если у вас не работает ОбработкаВыбора:

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

← На главную