При разработке механизмов автоматизации часто возникает задача запустить формирование внешнего отчета или выполнение логики внешней обработки в фоновом режиме (через регламентное задание). Казалось бы, алгоритм прост: извлечь файл из хранилища, создать объект и вызвать метод. Однако на практике разработчики часто сталкиваются с ошибкой "Метод объекта не обнаружен", даже если процедура явно объявлена как Экспорт в модуле объекта. В этой статье мы подробно разберем, почему это происходит и как правильно настроить программный вызов внешних файлов на сервере.
Проанализируем ситуацию: когда мы используем метод ВнешниеОтчеты.Создать() или ВнешниеОбработки.Создать(), платформа по умолчанию запускает этот объект в так называемом безопасном режиме. Это защитный механизм 1С, который ограничивает потенциально опасные действия программного кода, такие как доступ к файловой системе, работа с COM-объектами или выполнение привилегированных операций.
В контексте нашей проблемы важно то, что в безопасном режиме доступ к экспортным методам модуля объекта может быть ограничен или заблокирован, если система считает вызов небезопасным. Именно поэтому попытка вызвать лОтчет.СформироватьОтчет() приводит к тому, что платформа "не видит" этот метод. Выясним, как это исправить.
Для того чтобы предоставить программному коду внешнего отчета полные права и разрешить доступ к его методам, необходимо явно передать второй параметр в метод создания объекта. Рассмотрим рабочий пример кода, который решает проблему:
// Получаем ссылку на внешний отчет из справочника
СсылкаНаОтчет = Справочники.ВнешниеОбработки.НайтиПоКоду("00001");
// Извлекаем двоичные данные файла из хранилища
ДвоичныеДанные = СсылкаНаОтчет.ХранилищеВнешнейОбработки.Получить();
// Создаем временный файл на сервере
ИмяФайла = ПолучитьИмяВременногоФайла("epf");
ДвоичныеДанные.Записать(ИмяФайла);
Попытка
// Ключевой момент: второй параметр "Ложь" отключает безопасный режим
ОбъектОтчета = ВнешниеОтчеты.Создать(ИмяФайла, Ложь);
// Теперь экспортная процедура будет доступна
ОбъектОтчета.СформироватьОтчет();
Исключение
// Обязательно фиксируем ошибку в журнале регистрации
ЗаписьЖурналаРегистрации("ВыполнениеОтчета", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
КонецПопытки;
// Очистка временного файла
УдалитьФайлы(ИмяФайла);
В данном примере мы передаем Ложь вторым аргументом. Это сообщает платформе, что отчет должен работать с теми же правами, что и вызвавший его код (в данном случае — права пользователя, под которым запущено регламентное задание). Рассмотрим подробнее, на что еще стоит обратить внимание.
Существует более современный и производительный способ работы с внешними объектами на сервере — использование метода Подключить(). Вместо того чтобы каждый раз инициализировать файл напрямую, мы можем зарегистрировать его во временном хранилище менеджера.
Разберем, почему это удобно:
Пример использования метода Подключить:
// Подключаем отчет и получаем его внутреннее имя
ИмяВПамяти = ВнешниеОтчеты.Подключить(ИмяФайла, , Ложь);
// Создаем объект, используя полученное имя
ОбъектОтчета = ВнешниеОтчеты.Создать(ИмяВПамяти);
ОбъектОтчета.СформироватьОтчет();
Если ваш отчет был изначально разработан для "Обычных форм", при запуске в фоновом задании могут возникнуть дополнительные сложности. Выясним причины:
1. Отсутствие контекста клиента. Регламентное задание всегда выполняется на сервере. В модуле объекта не должно быть вызовов таких методов, как Предупреждение(), Вопрос(), Сообщить() (с привязкой к элементам формы) или ОткрытьФорму(). Если код внутри СформироватьОтчет() попытается обратиться к интерактивным функциям, задание завершится с критической ошибкой.
2. Директивы компиляции. Проверьте, чтобы ваша процедура СформироватьОтчет не была обернута в условия типа #Если Клиент Тогда. Для фонового задания код должен быть доступен серверу.
3. Работа с СКД. Если отчет построен на Системе компоновки данных, помните, что вызов простого метода модуля объекта не инициирует автоматический вывод в табличный документ, как это происходит при нажатии кнопки "Сформировать" в форме. Проанализируем, что должно быть внутри процедуры:
Процедура СформироватьОтчет() Экспорт
// Инициализация схемы и настроек
Схема = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
Настройки = КомпоновщикНастроек.ПолучитьНастройки();
// Подготовка макета компоновки
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, Настройки);
// Выполнение компоновки
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
// Вывод результата в таблицу или файл
Результат = Новый ТабличныйДокумент;
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(Результат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
// Сохранение результата, например, в PDF
Результат.Записать("C:\Reports\Report.pdf", ТипФайлаТабличногоДокумента.PDF);
КонецПроцедуры
При использовании ПолучитьИмяВременногоФайла() 1С создает реальный файл в системной директории сервера. Посмотрим на типичную ошибку: если регламентное задание запускается каждые 5 минут и не удаляет за собой файлы, дисковое пространство на сервере может закончиться очень быстро.
Всегда используйте конструкцию Попытка...Финально (или просто вызывайте УдалитьФайлы в конце процедуры), чтобы гарантировать чистоту системы. Помните, что автоматическая очистка временных файлов платформой происходит не мгновенно, а по завершении сеанса, который в случае с сервером приложений может длиться очень долго.
Начиная с версии платформы 8.3.9, даже при отключении безопасного режима может сработать Защита от опасных действий. Это системное окно, которое спрашивает разрешение на запуск внешнего кода. В фоновом задании нажать "Да" некому, поэтому задание просто зависнет или упадет.
Чтобы этого избежать, выполните одно из действий:
ОписаниеЗащитыОтОпасныхДействий в методах подключения, если ваша версия платформы и режим совместимости это поддерживают.Подведем итог: для успешного запуска внешнего кода из регламента необходимо обеспечить серверный контекст выполнения, программно отключить безопасный режим и корректно обработать жизненный цикл временных файлов. Следуя этим правилам, вы сможете реализовать надежную автоматизацию формирования отчетности в вашей системе.