Почему при программном открытии формы выбора значение не возвращается в поле ввода?

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

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

Анализ исходной ситуации

Рассмотрим код, который вызвал затруднения у автора темы. В процедуре НачалоВыбора разработчик отменяет стандартную обработку и вызывает собственную функцию для открытия формы:


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

Проанализируем функцию в общем модуле, которая отвечает за открытие формы:


Процедура ОткрытьФормуВыбораСОтбором(ИмяСправочника, Элемент, СтруктураОтбора) Экспорт
    ФормаВыбора = Справочники[ИмяСправочника].ПолучитьФормуВыбора(, Элемент, );
    // ... настройка отборов ...
    ФормаВыбора.Открыть();        
КонецПроцедуры

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

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

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

  1. После двойного клика по элементу в списке или нажатия кнопки «Выбрать» форма выбора закрывается.
  2. Выбранная ссылка автоматически записывается в данные, связанные с этим полем ввода.
  3. Инициируется стандартное событие ПриИзменении для этого элемента.

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

Чтобы исправить код, нам нужно передать в функцию открытия формы не ЭтаФорма, а параметр Элемент, который приходит в событие НачалоВыбора:


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

Решение №2: Ручная обработка выбора

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


Процедура ОбработкаВыбора(ЗначениеВыбора, Источник)
    // ЗначениеВыбора — это ссылка на выбранный элемент справочника
    // Проверяем, что выбор пришел именно из нужной нам формы или для нужного реквизита
    Если ТипЗнч(ЗначениеВыбора) = Тип("СправочникСсылка.Склады") Тогда
        СкладКомпании = ЗначениеВыбора; // Присваиваем значение реквизиту
        // Если нужно, вызываем обработчик изменения вручную
        СкладКомпанииПриИзменении(ЭлементыФормы.СкладКомпании);
    КонецЕсли;
КонецПроцедуры

Этот способ более трудозатратный и обычно используется в сложных случаях, например, при множественном подборе или когда логика возврата значения зависит от контекста.

Важные нюансы работы с отборами

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

СписокДоступныхСкладов.Добавить(СокрЛП(СтрокаТДС.Склад.Наименование));

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


СписокДоступныхСкладов = Новый СписокЗначений();
Для Каждого СтрокаТДС Из ТаблицаДоступныхСкладов Цикл
    // Добавляем ССЫЛКУ, а не строку
    СписокДоступныхСкладов.Добавить(СтрокаТДС.Склад);
КонецЦикла;    

// Накладываем отбор по полю "Ссылка"
СтруктураОтбора = Новый Структура("Ссылка", СписокДоступныхСкладов);

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


Если ТипЗнч(ЭлементСтруктуры.Значение) = Тип("СписокЗначений") Тогда
    ФормаВыбора.Отбор[ЭлементСтруктуры.Ключ].ВидСравнения = ВидСравнения.ВСписке;
КонецЕсли;

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

Рассмотрим еще один важный момент. Когда мы пишем СтандартнаяОбработка = Ложь в самом начале процедуры, мы берем на себя полную ответственность за результат. Если в вашем коде возникнет ошибка до вызова Открыть() или список доступных значений окажется пустым и условие Если ... Тогда не сработает, пользователь просто увидит, что кнопка выбора «зависла» и ничего не происходит.

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

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

← На главную