Как правильно открыть форму выбора и вернуть значение в управляемых формах 1С 8.3

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

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

В чем заключается основная проблема?

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

Если в этом обработчике жестко прописать возврат текущей строки списка, то при отмене выбора (нажатии на «крестик») вызывающая форма все равно получит данные текущей строки вместо ожидаемого Неопределено. Это делает невозможным программное определение того, совершил ли пользователь выбор или просто закрыл окно.

Способ 1: Использование метода ОповеститьОВыборе

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

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

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


&НаКлиенте
Процедура СписокВыборЗначения(Элемент, Значение, СтандартнаяОбработка)
    // Отменяем стандартную обработку, чтобы система не пыталась сама вернуть ссылку
    СтандартнаяОбработка = Ложь;
    
    // Получаем нужные данные из текущей строки
    ТекущиеДанные = Элементы.Список.ТекущиеДанные;
    Если ТекущиеДанные <> Неопределено Тогда
        // Оповещаем систему о том, что выбор совершен
        ОповеститьОВыборе(ТекущиеДанные.Адрес);
    КонецЕсли;
КонецПроцедуры

Способ 2: Настройка основной таблицы динамического списка

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

Многие полагают, что в сложном запросе нельзя указать основную таблицу, но это заблуждение. Чтобы форма выбора работала в стандартном режиме (без лишнего кода):

  1. Откройте свойства динамического списка в конфигураторе.
  2. В поле Основная таблица выберите соответствующий справочник или документ.
  3. Убедитесь, что поле Ссылка выбрано в вашем запросе.

После этого стандартный выбор начнет возвращать ссылку на объект, а не его ID.

Способ 3: Программное открытие с описанием оповещения

Разберем, как правильно инициировать выбор из вызывающей формы. Мы используем асинхронный подход, который является стандартом для современной платформы 8.3.


&НаКлиенте
Процедура ВыбратьАдрес(Команда)
    // Формируем параметры открытия
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("ЗакрыватьПриВыборе", Истина);
    
    // Создаем описание оповещения, которое сработает после закрытия формы выбора
    ОписаниеОповещения = Новый ОписаниеОповещения("АдресаДоставкиЗавершениеВыбора", ЭтотОбъект);
    
    // Открываем форму
    ОткрытьФорму("Справочник.АдресаДоставки.Форма.ФормаВыбора", 
                 ПараметрыФормы, 
                 Элементы.ПолеВводаАдреса, // Владелец
                 УникальныйИдентификатор, 
                 , 
                 , 
                 ОписаниеОповещения, 
                 ВариантОткрытияОкна.ОтдельноеОкно);
КонецПроцедуры

&НаКлиенте
Процедура АдресаДоставкиЗавершениеВыбора(РезультатВыбора, ДополнительныеПараметры) Экспорт
    // Если пользователь нажал Esc или крестик, РезультатВыбора будет Неопределено
    Если РезультатВыбора <> Неопределено Тогда
        Объект.АдресДоставки = РезультатВыбора;
    КонецЕсли;
КонецПроцедуры

Нюансы работы с произвольными данными

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

  1. Установите у динамического списка свойство РежимВыбора в значение Ложь. Это отключит стандартную попытку системы найти ссылку.
  2. Переопределите событие списка Выбор или ВыборЗначения.
  3. В обработчике используйте ОповеститьОВыборе(НужноеЗначение).

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

Типичная ошибка с потерей кнопок поиска

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

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

← На главную