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