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