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