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