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