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