Как правильно работать с реквизитами формы и модуля объекта в управляемых формах 1С

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

При переходе с обычных форм на управляемые разработчики часто сталкиваются с непониманием клиент-серверной архитектуры платформы 1С:Предприятие 8. Типичные симптомы — значения реквизитов пропадают между вызовами сервера, попытка передать объект из модуля формы в модуль объекта вызывает ошибку несоответствия типов, а передача специализированных объектов (например, узлов XML) приводит к загадочной «ошибке отображения». Разберем подробно, почему так происходит, как устроена работа с данными формы и как правильно реализовать отображение хода длительной операции.

Различие между реквизитами формы и реквизитами объекта

Проанализируем базовую концепцию управляемого интерфейса. В управляемых формах существует строгое разделение между данными, отображаемыми на клиенте, и прикладными объектами базы данных на сервере:

  1. Реквизиты объекта — это данные, определенные в метаданных конфигурации (например, реквизиты справочника, документа или обработки). В модуле объекта к ним обращаются напрямую через ЭтотОбъект.ИмяРеквизита или просто по имени. Модуль объекта ничего не знает о существовании интерфейса и не имеет доступа к контексту открытых окон.
  2. Реквизиты формы — это временные данные, существующие только в контексте открытой формы. Основной реквизит формы (обычно с именем Объект) имеет специальный внутренний тип ДанныеФормыСтруктураДляОбъекта. Он представляет собой легковесную проекцию данных, предназначенную для передачи между клиентом и сервером по сети, но не содержит методов самого прикладного объекта.

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

Бессерверная модель и правильная работа с модулем объекта

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

Для обращения к экспортным методам модуля объекта из модуля формы необходимо явно выполнять преобразование данных формы в прикладной объект и обратно. Посмотрим на классический шаблон такого вызова на сервере:


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

Важно различать пары системных функций преобразования данных:

  1. Методы РеквизитФормыВЗначение и ЗначениеВРеквизитФормы предназначены исключительно для работы с основным объектом формы (справочник, документ, обработка).
  2. Методы ДанныеФормыВЗначение и ЗначениеВДанныеФормы применяются только к универсальным коллекциям формы (таблицы, деревья, списки значений), преобразуя их в стандартные объекты ТаблицаЗначений, СписокЗначений и обратно. Передача в них объекта конфигурации или попытка вызвать их внутри модуля объекта приведет к ошибке несоответствия типов.

Почему возникает ошибка отображения при работе с XML

Рассмотрим распространенную ошибку: попытку выполнять разбор XML на клиенте и передавать узлы ЭлементDOM параметрами в серверные процедуры для обновления интерфейса. При таком вызове платформа генерирует системную «ошибку отображения».

Причина кроется в механизме сетевой сериализации. Между клиентом и сервером могут передаваться только те типы данных, которые платформа умеет упаковывать в сетевые пакеты (примитивные типы, структуры, массивы, ссылки, данные формы). Объекты ЭлементDOM, ДокументDOM, ЧтениеXML и ЗаписьXML являются тяжелыми системными объектами и не подлежат сериализации (маршалингу). Их категорически нельзя передавать через границу клиент-сервер.

Кроме того, синхронный вызов серверной процедуры намертво блокирует пользовательский интерфейс на клиенте. Пока серверный метод не завершится целиком, клиент не сможет отобразить изменения реквизитов, а вызовы ОбновитьОтображениеДанных() не возымеют эффекта в процессе выполнения операции.

Архитектурно верные способы отображения прогресса

Для реализации индикации длительного процесса и парсинга больших файлов разберем два надежных сценария.

Способ 1. Запуск длительной операции через фоновое задание (рекомендуемый подход)

Это штатный механизм для современных конфигураций. Основная работа выносится в фоновый поток на сервере, а форма периодически опрашивает состояние выполнения через обработчик ожидания.

  1. Файл с клиента целиком отправляется во временное хранилище с помощью метода ПоместитьФайлНаСервер().
  2. На сервере запускается фоновое задание через ФоновыеЗадания.Выполнить() или функции БСП ДлительныеОперации.ВыполнитьВФоне().
  3. Фоновый поток разбирает файл на сервере. При этом для больших файлов вместо прожорливой объектной модели DOM рекомендуется использовать потоковый объект ЧтениеXML.
  4. О ходе выполнения фоновое задание сообщает через временное хранилище или механизм сообщений: ФоновоеЗадание.ПолучитьСообщенияПользователю().
  5. На клиенте подключается таймер через ПодключитьОбработчикОжидания(), который опрашивает задание, считывает процент выполнения и плавно двигает индикатор на форме без зависания интерфейса.

Способ 2. Пошаговая порционная обработка с клиента

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

  1. Файл загружается на сервер один раз, а промежуточный контекст сохраняется во временном хранилище с привязкой к форме: ПоместитьВоВременноеХранилище(Данные, УникальныйИдентификатор). Хранилище с привязкой к форме автоматически очистится при ее закрытии.
  2. Клиент запускает обработчик ожидания и короткими серверными вызовами запрашивает обработку пачки данных (например, по 100 элементов XML).
  3. После возврата каждого серверного вызова клиентская процедура обновляет реквизиты формы, отображает текст в строке состояния методом Состояние() и вызывает ОбработкаПрерыванияПользователя(), позволяя пользователю прервать операцию.

Таким образом, правильное проектирование управляемой формы исключает хранение состояния в переменных модуля объекта и перенос несериализуемых объектов через клиент-серверную границу, обеспечивая стабильную и отзывчивую работу интерфейса.

← На главную