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

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

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

Выясняем причину: ловушка разных экземпляров объекта

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

Представим этот процесс: в основной форме у вас есть Объект (экземпляр №1). При открытии дополнительной формы система создает еще один Объект (экземпляр №2). Когда вы записываете данные в реквизиты во второй форме, вы меняете состояние экземпляра №2. Как только эта форма закрывается, экземпляр №2 уничтожается, а экземпляр №1 в основной форме так и остается с пустыми полями. Таким образом, работа с Объект.ИмяРеквизита напрямую из разных форм одной обработки не обеспечивает автоматическую синхронизацию данных.

Решение 1: Использование механизма выбора (ОповеститьОВыборе)

Наиболее правильным и архитектурно верным способом в управляемом приложении является использование стандартного механизма выбора. Рассмотрим этот метод по шагам.

Во вспомогательной форме, после того как пользователь заполнил данные и нажал кнопку "ОК" или "Завершить", мы не просто закрываем форму, а передаем структуру данных назад.

Пример кода в дополнительной форме:


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

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

Пример кода в основной форме:


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

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

Решение 2: Передача данных через владельца формы напрямую

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

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


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

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

Решение 3: Использование временного хранилища для больших объемов данных

Если из дополнительной формы нужно передать не просто пару значений, а целую таблицу значений или сложный массив данных, лучше использовать ПоместитьВоВременноеХранилище. Проанализируем, как это реализовать.

  1. В дополнительной форме на сервере помещаем данные в хранилище и получаем Адрес.
  2. Передаем этот Адрес в основную форму (через тот же ОповеститьОВыборе).
  3. В основной форме на сервере извлекаем данные по адресу.

Пример кода (серверная часть дополнительной формы):


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

Синхронизация данных: РеквизитФормыВЗначение и ЗначениеВРеквизитФормы

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

Посмотрим на пример кода на сервере:


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

Этот механизм критически важен, так как без вызова ЗначениеВРеквизитФормы все изменения, сделанные в коде модуля объекта, не отобразятся в интерфейсе пользователя, и поля будут казаться пустыми.

Итоги и рекомендации

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

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

← На главную