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