Как вернуть значение в реквизит документа, если стандартная форма выбора была заменена?

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

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

Анализ проблемы: почему нарушается стандартное поведение?

Для начала проанализируем, что происходит "под капотом" платформы 1С. Когда вы в поле ввода нажимаете кнопку выбора или кнопку создания ("+"), форма-владелец (в нашем случае, форма документа) переходит в режим ожидания выбора.

  1. Стандартный сценарий (создание нового): При нажатии на "+" открывается форма нового элемента справочника. Вы заполняете данные, нажимаете "Записать и закрыть". Платформа понимает, что эта форма была открыта для выбора, и после успешной записи автоматически возвращает ссылку на новый элемент в исходное поле документа. Контекст вызова сохраняется, и все работает штатно.
  2. Наш сценарий (выбор существующего): Логика усложняется. Вы нажимаете "+", но вместо простого создания происходит обращение к внешнему API. API сообщает, что такой элемент уже есть, и вы программно, методом ОткрытьФорму(), открываете форму этого существующего элемента. В этот момент платформа теряет исходный контекст. Она не "понимает", что открытие этой формы является частью процесса выбора для документа. Для нее это просто независимое открытие формы. Соответственно, когда вы ее закроете, никакого значения в документ не вернется.

Таким образом, наша задача — восстановить эту нарушенную связь и явно сообщить форме документа, что выбор завершен и вот его результат.

Решение: используем механизм оповещений с помощью `ОповеститьОВыборе`

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

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

Разберем по шагам, как его применить.

  1. Точка вызова. Ключевое действие должно происходить в той форме, которая является конечной точкой выбора. В нашем случае, это форма существующего элемента справочника, которую мы открыли после обнаружения дубликата.
  2. Добавление элемента управления. Поскольку пользователь должен как-то подтвердить свой выбор, логично добавить на эту форму кнопку, например, с названием "Выбрать". Пользователь, убедившись, что это нужный элемент, нажмет на нее.
  3. Написание кода. В обработчике команды этой кнопки на клиенте нужно написать всего одну строку кода.

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

    
    &НаКлиенте
    Процедура ВыбратьЭлемент(Команда)
        // Оповещаем форму-владельца о том, что выбор сделан.
        // В качестве параметра передаем ссылку на текущий элемент.
        ОповеститьОВыборе(Объект.Ссылка);
    
        // Можно также сразу закрыть форму, чтобы не мешать пользователю.
        ЭтаФорма.Закрыть();
    КонецПроцедуры
    

Как это сработает? Когда будет выполнен метод ОповеститьОВыборе(Объект.Ссылка), произойдет следующее:

Проблема решена! Мы явно указали платформе, какой элемент был выбран, и она корректно завершила операцию выбора.

Дополнительная логика: событие `ОбработкаВыбора`

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

Посмотрим на пример. Допустим, у нас есть реквизит документа ФизЛицо, и мы хотим после его выбора автоматически заполнять реквизит ИНН.


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

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

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

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

КонецФункции

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

Альтернативные, но менее подходящие механизмы

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

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

← На главную