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

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

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

Почему нельзя использовать экспортные переменные модуля формы

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

  1. Жизненный цикл формы: Экспортные переменные клиентского модуля формы существуют исключительно в оперативной памяти клиентского приложения и только пока форма остается открытой. Как только пользователь нажимает кнопку подтверждения или закрывает окно, экземпляр формы уничтожается сборщиком мусора. Попытка прочитать переменную по ссылке на закрытую форму вызовет исключение платформы.
  2. Отсутствие серверного контекста: Клиентские переменные формы не передаются на сервер при контекстных вызовах (&НаСервере) и не сохраняются между серверными вызовами, в отличие от реквизитов формы.
  3. Нарушение инкапсуляции: Прямая модификация или опрос состояния дочерней формы связывает модули жесткой зависимостью, затрудняет отладку и не инициирует стандартные события обновления пользовательского интерфейса.

Рассмотрим правильный архитектурный шаблон платформы 1С — асинхронную передачу результата через механизм оповещений.

Пошаговое решение: передача результата через ОписаниеОповещения и метод Закрыть()

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

Шаг 1. Открытие формы и установка обработчика оповещения

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


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

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

Шаг 2. Прием исходных параметров во вспомогательной форме

Проанализируем получение данных открываемой формой. Начальные значения передаются во втором параметре метода ОткрытьФорму() и считываются в процедуре ПриСозданииНаСервере через свойство Параметры:


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

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

Шаг 3. Завершение ввода и возврат данных

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


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

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

Шаг 4. Обработка полученного результата в вызывающей форме

В модуле формы элемента справочника создадим экспортируемую или локальную клиентскую процедуру, имя которой было указано в ОписаниеОповещения. Обязательно проверяем значение параметра РезультатЗакрытия на равенство Неопределено — это значение платформа возвращает, если пользователь закрыл окно крестиком, клавишей Esc или системной командой без подтверждения:


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

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

Особенности: Закрыть() против ОповеститьОВыборе()

Рассмотрим подробнее разницу между методами Закрыть() и ОповеститьОВыборе() при передаче данных владельцу формы:

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

Альтернативные способы передачи данных

В зависимости от архитектуры задачи можно рассмотреть еще два механизма взаимодействия:

  1. Глобальный механизм оповещений (Оповестить / ОбработкаОповещения): Метод Оповестить(ИмяСобытия, Параметр, Источник) позволяет рассылать широковещательные события всем открытым окнам приложения. Вызывающая форма может перехватить его через процедуру ОбработкаОповещения. Этот вариант удобен, когда форма ввода не подчинена жестко одной вызывающей форме, но требует ручной фильтрации источников событий.
  2. Передача данных через Временное хранилище: Если состав возвращаемых данных велик (например, файлы, тяжелые таблицы или бинарные данные), передавать их напрямую через клиентские параметры не рекомендуется. В таком случае дочерняя форма помещает структуру в хранилище с помощью ПоместитьВоВременноеХранилище(), а в метод Закрыть() передает только полученный строковый адрес хранилища.

Рекомендации для типовых конфигураций

Если задача решается в конфигурации на базе Библиотеки стандартных подсистем (БСП), не требуется разрабатывать собственные формы для ввода адресов. В БСП включена подсистема управления контактной информацией. В ней данные адреса хранятся внутри реквизитов объекта в виде форматированного XML/JSON, для пользователя выводится строковое представление, а редактирование выполняется типовой формой ввода адреса с интеграцией адресного классификатора.

← На главную