Как записать документ из управляемой формы на клиенте и передать данные на сервер в 1С 8.3?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке в среде управляемого приложения 1С начинающие программисты нередко сталкиваются с трудностями при попытке программно заполнить и записать документ через полученную форму на клиенте. Попытка передать саму форму или ее реквизит Объект в серверную процедуру приводит к системным ошибкам платформы. Разберем, почему возникают эти ошибки и как правильно решать задачи создания, изменения и записи документов.

Причины возникновения ошибок передачи формы на сервер

Проанализируем две типичные ситуации, приводящие к сбоям:

  1. Ошибка передачи типа «УправляемаяФорма» между клиентом и сервером. Объект типа УправляемаяФорма не сериализуется (для него отсутствует отображение типов XDTO). Форма существует на клиенте как визуальный интерфейс и не может быть передана в качестве параметра во внеконтекстную процедуру &НаСервереБезКонтекста или в общий модуль. Контекст формы доступен на сервере исключительно внутри процедур с директивой &НаСервере самого модуля этой же формы.
  2. Ошибка «Нельзя изменять поле, содержащее объект данных формы». Реквизит формы Объект имеет тип ДанныеФормыСтруктура. Платформа блокирует прямое присваивание значения переменной реквизита (например, ФормаДокумента.Объект = НовыеДанные), чтобы не нарушать внутренние механизмы привязки элементов интерфейса к данным.

Рассмотрим несколько корректных способов решения задачи в зависимости от стоящей цели.

Способ 1. Запись документа на клиенте с помощью метода формы Записать()

Если форма документа уже получена или открыта на клиенте, для ее сохранения не требуется создавать отдельные серверные процедуры. Управляемая форма предоставляет встроенный метод Записать(), который доступен на клиенте. Данный метод автоматически передает данные на сервер, инициирует выполнение стандартных событий формы (ПередЗаписьюНаСервере, ПриЗаписиНаСервере, ПослеЗаписи) и выполняет запись самого объекта в базу данных.

Посмотрим на пример клиентского вызова:


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

Способ 2. Разделение бизнес-логики и интерфейса (создание объекта на сервере)

В архитектуре управляемого приложения манипуляции с экранными формами ради фонового создания или изменения записей в базе данных считаются неоптимальным подходом. Форма предназначена для взаимодействия с пользователем. Если интерактивный ввод не требуется, правильнее выполнить всю цепочку действий на сервере через объектную модель 1С, а на клиент вернуть готовую ссылку.

Разберем реализацию такого подхода по шагам:

  1. Передаем с клиента на сервер только прикладные данные (структуру с реквизитами для заполнения).
  2. На сервере создаем экземпляр документа через менеджер объекта, заполняем реквизиты и записываем его.
  3. Возвращаем ссылку на созданный документ на клиент. При необходимости открываем форму уже созданного документа.

Посмотрим на пример кода:


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

&НаСервереБезКонтекста
Функция СоздатьИЗаписатьДокументНаСервере(ДанныеЗаполнения)
    НовыйДокумент = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
    НовыйДокумент.Дата = ТекущаяДатаСеанса();
    НовыйДокумент.Организация = ДанныеЗаполнения.Организация;
    НовыйДокумент.Контрагент = ДанныеЗаполнения.Контрагент;
    
    // Заполняем остальные реквизиты и табличные части
    НовыйДокумент.Записать(РежимЗаписиДокумента.Запись);
    
    Возврат НовыйДокумент.Ссылка;
КонецФункции

Способ 3. Синхронизация данных формы через КопироватьДанныеФормы

Если стоит задача изменить данные в уже открытой форме документа с помощью серверных алгоритмов, передавать на сервер нужно не форму, а ее реквизит Объект (имеющий тип ДанныеФормыСтруктура). Для обратной записи измененных данных в форму на клиенте используется процедура КопироватьДанныеФормы().

Разберем, как устроен этот механизм:


&НаКлиенте
Процедура ОбработатьИЗаписатьДанныеФормы(ФормаДокумента)
    // Передаем данные формы на сервер
    ОбновленныеДанные = ЗаполнитьИЗаписатьНаСервере(ФормаДокумента.Объект);
    
    // Корректно переносим обновленные данные обратно в форму
    КопироватьДанныеФормы(ОбновленныеДанные, ФормаДокумента.Объект);
КонецПроцедуры

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

Способ 4. Передача значений заполнения при открытии новой формы

Если требуется открыть для пользователя новую форму документа, предварительно заполнив ее определенными значениями без немедленной записи в базу, используем штатный механизм платформы — параметр ЗначенияЗаполнения.

Посмотрим на пример:


&НаКлиенте
Процедура ОткрытьНовыйЗаполненныйДокумент()
    СтруктураЗаполнения = Новый Структура;
    СтруктураЗаполнения.Вставить("Контрагент", ВыбранныйКонтрагент);
    СтруктураЗаполнения.Вставить("ДоговорКонтрагента", ВыбранныйДоговор);
    
    ПараметрыФормы = Новый Структура("ЗначенияЗаполнения", СтруктураЗаполнения);
    
    ОткрытьФорму("Документ.РеализацияТоваровУслуг.ФормаОбъекта", ПараметрыФормы);
КонецПроцедуры

При таком вызове платформа автоматически передает параметры в обработчик ОбработкаЗаполнения модуля объекта на сервере, заполняет реквизиты формы и отображает ее пользователю в готовом для дальнейшей работы виде.

← На главную