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

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

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

Способ 1: Использование модального режима (для обычных форм и совместимости)

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

Для реализации этого метода проанализируем следующий код в обработчике события НачалоВыбора:


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

Важный нюанс: Чтобы этот способ работал, в свойствах конфигурации должен быть разрешен режим использования модальности. Если вы работаете в веб-клиенте или в конфигурации с установленным свойством "Режим использования модальности — Не использовать", этот код вызовет ошибку.

Способ 2: Асинхронный метод с использованием ОписанияОповещения

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

Рассмотрим реализацию по шагам. Сначала подготовим основную процедуру:


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

Теперь создадим процедуру-обработчик, которая примет результат выбора:


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

Обратите внимание на ключевое слово Экспорт — процедура оповещения обязательно должна быть экспортной, иначе платформа не сможет к ней обратиться.

Способ 3: Автоматическая подстановка через Владельца формы

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

Посмотрим на пример упрощенного кода:


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

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

Способ 4: Программная настройка динамического списка в форме выбора

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


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

Типичные ошибки и их решение

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

  1. Отсутствие владельца: Если при открытии формы в параметрах не указан владелец (Элемент или ЭтаФорма), метод ОповеститьОВыборе "уйдет в никуда", так как форме некому возвращать результат.
  2. Неправильный тип возврата: Убедитесь, что в процедуре Закрыть() передается ссылка на объект (например, СправочникСсылка), а не строка или вся строка таблицы значений целиком.
  3. Конфликт обработчиков: Если вы используете СтандартнаяОбработка = Ложь, вы берете на себя всю ответственность за заполнение реквизита. Платформа больше не будет пытаться автоматически записать выбранное значение, если вы не указали владельца.
  4. РежимВыбора: При программном открытии нетиповых форм обязательно передавайте параметр РежимВыбора = Истина в структуру параметров, иначе двойной клик в форме выбора будет открывать карточку объекта вместо возврата значения.

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


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

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

← На главную