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