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

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

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

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

---

Метод 1. Использование описания оповещения при закрытии (Рекомендуемый стандарт)

Начиная с платформы 8.3, фирма «1С» настоятельно рекомендует отказываться от модальных окон (таких как метод ОткрытьМодально). Модальность блокирует интерфейс, создает избыточную нагрузку и полностью несовместима с работой в веб-клиенте через стандартные браузеры, а также в мобильном клиенте.

Современный асинхронный подход базируется на использовании объекта ОписаниеОповещения и передаче параметров при закрытии формы. Рассмотрим этот процесс по шагам.

Шаг 1. Настройка основной формы

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


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

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

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

Шаг 2. Настройка формы настроек

В форме настроек мы считываем переданные параметры при создании формы на сервере, а при подтверждении выбора закрываем форму, возвращая структуру данных обратно.


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Заполняем реквизиты формы настроек переданными параметрами
    ЗаполнитьЗначенияСвойств(Объект, Параметры);
    
КонецПроцедуры

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

---

Метод 2. Прямое изменение данных через «ВладелецФормы»

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

Этот способ отлично подходит для простых утилит, калькуляторов параметров или форм быстрого подбора. При этом важно, чтобы при открытии вспомогательного окна в качестве владельца была передана основная форма (параметр ЭтаФорма).

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

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

Преимущества метода: Высокая скорость реализации и мгновенный интерактивный отклик в основном окне.

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

---

Метод 3. Обмен данными через глобальные оповещения

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

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

Код в отправляющей форме настроек:


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

Код в принимающей (основной) форме:


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

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

---

Метод 4. Оптимальная передача больших таблиц через «Временное хранилище»

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

Для оптимизации трафика задействуем механизм ВременноеХранилище. Вместо пересылки самих данных мы передадим лишь короткую строку-адрес во временном хранилище.

Схема реализации выглядит следующим образом:

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

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

---

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

Выбор конкретного метода обмена данными зависит от архитектуры вашей обработки:

← На главную