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

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

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

Способ 1. Использование механизма Оповестить и ОбработкаОповещения

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

Реализация в подчиненной форме (отправитель):

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


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

Реализация в основной форме (получатель):

В основной форме необходимо создать предопределенный обработчик ОбработкаОповещения.


&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
    // Проверяем, то ли это событие, которое мы ждем
    Если ИмяСобытия = "ОбновитьЗначениеЦены" Тогда
        Объект.Значение = Параметр;
        Сообщить("Данные успешно получены: " + Параметр);
    КонецЕсли;
КонецПроцедуры

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

Способ 2. Использование ОписанияОповещения (Рекомендуемый)

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

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

Шаг 1. Открытие формы в основном окне:

Вместо простого открытия мы подготавливаем объект, который «знает», куда вернуться.


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

Шаг 2. Возврат значения из вспомогательной формы:

В подчиненной форме при закрытии мы просто передаем результат в метод Закрыть().


&НаКлиенте
Процедура КомандаОК(Команда)
    Результат = Объект.НовоеЗначение;
    // Передаем результат прямо в метод Закрыть
    ЭтаФорма.Закрыть(Результат);
КонецПроцедуры

Шаг 3. Обработка результата в основной форме:

Создаем экспортную процедуру, имя которой мы указали при создании ОписаниеОповещения.


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

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

Способ 3. ОповеститьОВыборе и ОбработкаВыбора

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

1. В основной форме при открытии вспомогательной формы обязательно указывайте владельца: ОткрытьФорму("...", Параметры, ЭтаФорма).
2. В подчиненной форме вызовите метод ОповеститьОВыборе(Значение).
3. В основной форме данные автоматически попадут в обработчик события ОбработкаВыбора(ВыбранноеЗначение, Источник).

Этот способ является «чистым» с точки зрения архитектуры платформы 1С, так как использует штатные события выбора объектов.

Дополнительные советы для продвинутой разработки

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

  1. Временное хранилище: Если данных много, поместите их во временное хранилище в подчиненной форме на сервере, а обратно передайте только Адрес (строку). Основная форма по этому адресу сможет прочитать данные уже на своей стороне сервера.
  2. Уникальный идентификатор: Если вы все же вынуждены использовать глобальное Оповестить, передавайте в структуре параметров УникальныйИдентификатор основной формы. В обработчике ОбработкаОповещения проверяйте, совпадает ли идентификатор источника или адресата с текущей формой.
  3. Асинхронность (для новых платформ): Начиная с версии 8.3.18, можно использовать ОткрытьФормуАсинх и оператор Ждать. Это позволяет писать код линейно, не создавая отдельные процедуры завершения.

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

← На главную