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

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

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

Метод 1: Использование «ОписаниеОповещения» и метода «Закрыть»

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

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


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

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

Теперь проанализируем, что нужно написать в дочерней форме. Чтобы данные вернулись в основную форму, их нужно передать в качестве параметра метода Закрыть().


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

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

Метод 2: Использование «ОповеститьОВыборе» и «ОбработкаВыбора»

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

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

В основной форме реализуем обработчик события:


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

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


&НаКлиенте
Процедура СписокВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    // Данный метод инициирует событие ОбработкаВыбора у владельца
    ОповеститьОВыборе(ВыбраннаяСтрока);
    
КонецПроцедуры

Метод 3: Глобальные оповещения через «Оповестить»

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

Проанализируем работу системы событий. Когда вызывается Оповестить(), сообщение рассылается всем открытым формам. Те формы, в которых прописана процедура ОбработкаОповещения, смогут его принять.

В форме-отправителе (дочерней):


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

В основной форме (или любой другой):


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

Сложные типы данных и передача через структуру

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

Пример упаковки данных в дочерней форме:


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

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

Важные нюансы: контекст и временное хранилище

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

  1. В дочерней форме данные помещаются во Временное хранилище на сервере.
  2. Метод Закрыть() возвращает только строковый адрес этого хранилища (URL).
  3. Основная форма получает адрес и на сервере извлекает данные методом ПолучитьИзВременногоХранилища().

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

Резюмируем: для простых случаев возврата одного значения лучше всего подходит пара ОписаниеОповещения + Закрыть(Результат). Для подбора элементов из списка оптимально использовать ОповеститьОВыборе(). Глобальное Оповестить() стоит оставить для случаев синхронизации данных между несвязанными окнами.

← На главную