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