Как получить данные из другой формы после её закрытия в 1С?

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

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

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

Способ 1: Использование модальных окон (устаревший подход)

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

Как это работает?

Механизм следующий:

  1. Из основной формы вызывается вспомогательная с помощью метода ОткрытьФормуМодально(). Выполнение кода в основной форме на этой строке приостанавливается.
  2. Пользователь работает со вспомогательной формой и, завершив работу, нажимает кнопку (например, "ОК" или "Выбрать").
  3. В обработчике этой кнопки во вспомогательной форме вызывается метод Закрыть(), в который в качестве параметра передается возвращаемое значение.
  4. После закрытия вспомогательной формы выполнение кода в основной форме возобновляется, и метод ОткрытьФормуМодально() возвращает то значение, которое было передано в метод Закрыть().

Пример реализации

Рассмотрим код для обеих форм.

Код в основной форме (Форма А):


&НаКлиенте
Процедура ОткрытьФормуБ(Команда)
    
    // Открываем форму Б модально и ждем результат
    ВозвращенноеЗначение = ОткрытьФормуМодально("ОбщаяФорма.ФормаБ");
    
    // Проверяем, что пользователь что-то выбрал, а не просто закрыл форму
    Если ВозвращенноеЗначение <> Неопределено Тогда
        Сообщить("Из формы Б было возвращено значение: " + ВозвращенноеЗначение);
        // Здесь можно дальше обрабатывать полученное значение
    КонецЕсли;
    
КонецПроцедуры

Код во вспомогательной форме (Форма Б):

Предположим, на форме есть поле ввода ДанныеДляВозврата и кнопка "ОК".


&НаКлиенте
Процедура ОК(Команда)
    
    // Получаем значение, которое нужно вернуть
    Результат = ДанныеДляВозврата; 
    
    // Закрываем форму и передаем результат в качестве параметра
    Закрыть(Результат);
    
КонецПроцедуры

Ключевой момент: если вызвать Закрыть() без параметра, то ОткрытьФормуМодально() вернет Неопределено. Именно это является частой ошибкой начинающих разработчиков.

Недостатки модального подхода

Несмотря на кажущуюся простоту, у этого метода есть серьезные минусы, из-за которых его использование в современных системах считается плохой практикой:

Способ 2: Асинхронная работа с помощью оповещений (рекомендуемый)

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

Как это работает?

Механизм основан на объекте ОписаниеОповещения.

  1. В основной форме перед открытием дочерней создается специальный объект ОписаниеОповещения. В нем мы указываем, какую процедуру нужно вызвать после того, как дочерняя форма завершит свою работу.
  2. Дочерняя форма открывается обычным методом ОткрытьФорму(), куда последним параметром передается созданное нами оповещение.
  3. Пользователь работает с дочерней формой.
  4. Когда нужно вернуть результат, в дочерней форме вызывается метод ОповеститьОВыборе(Результат) или Закрыть(Результат).
  5. Платформа вызывает процедуру-обработчик в основной форме и передает в нее результат из дочерней.

Пример реализации по шагам

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

Шаг 1. Код в основной форме (Форма А)

Здесь нам нужна команда для открытия формы и процедура-обработчик, которая примет результат.


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

// 3. Создаем экспортную процедуру-обработчик.
&НаКлиенте
Процедура ПослеЗакрытияФормыБ(ВозвращаемоеЗначение, ДополнительныеПараметры) Экспорт
    
    // Проверяем, что нам что-то вернули.
    Если ВозвращаемоеЗначение <> Неопределено Тогда
        Сообщить("Из формы Б асинхронно получено значение: " + ВозвращаемоеЗначение);
    Иначе
        Сообщить("Форма Б была закрыта без выбора значения.");
    КонецЕсли;
    
КонецПроцедуры

Важные моменты:

Шаг 2. Код во вспомогательной форме (Форма Б)

Код в дочерней форме становится даже проще. Мы просто должны вернуть результат.


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

Выводы и рекомендации

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

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

← На главную