При разработке внешних печатных форм или обработок в среде 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда код, успешно работающий во встроенных метаданных, выдает ошибку при попытке обращения к макету внешней обработки. Самая распространенная ошибка в этом случае звучит так: «Поле объекта не обнаружено (ИмяВашейОбработки)». Давайте детально разберем, почему это происходит и как правильно организовать вывод табличного документа на серверной стороне.
Разберем первопричину проблемы. Когда мы пишем код ВнешниеОбработки.ПоРодителямПраваОбъектов.ПолучитьМакет("Макет"), система 1С ожидает, что в менеджере ВнешниеОбработки существует предопределенный объект с таким именем. Однако, в отличие от справочников или документов, менеджер внешних обработок не хранит в себе коллекцию файлов, находящихся на диске или загруженных в базу через файл-меню. Менеджер ВнешниеОбработки предназначен исключительно для работы с программным интерфейсом: создания (Создать()), подключения (Подключить()) или выбора внешних обработок.
Проанализируем контекст управляемого приложения. В управляемой форме основной реквизит Объект имеет тип ДанныеФормыСтруктура. Этот тип является лишь облегченной «оболочкой» данных и не содержит в себе методов реального прикладного объекта, таких как ПолучитьМакет(). Именно поэтому попытка вызвать получение макета напрямую из реквизита формы или через менеджер приводит к аварийному завершению работы кода.
Рассмотрим основной и самый правильный способ решения проблемы в контексте управляемой формы. Чтобы получить доступ к методам объекта (включая работу с макетами), нам необходимо временно преобразовать данные формы в полноценный экземпляр объекта ВнешняяОбработкаОбъект.
Для этого в языке 1С предусмотрена системная функция РеквизитФормыВЗначение(). Посмотрим на примере, как должен выглядеть исправленный код процедуры на сервере:
&НаСервере
Процедура ПроверитьПоРодителямНаСервере()
// Преобразуем данные формы в объект внешней обработки
ОбъектОбработка = РеквизитФормыВЗначение("Объект");
// Теперь у нас есть доступ к методу ПолучитьМакет()
Макет = ОбъектОбработка.ПолучитьМакет("Макет");
// Далее работаем с макетом как обычно
Запрос = Новый Запрос;
// ... ваш текст запроса ...
РезультатЗапроса = Запрос.Выполнить();
ОбластьЗаголовок = Макет.ПолучитьОбласть("Заголовок");
// ... заполнение областей ...
КонецПроцедуры
Важный нюанс: Метод РеквизитФормыВЗначение работает исключительно на сервере. После получения объекта вы можете использовать любые его экспортные методы и обращаться к макетам. Однако помните, что изменения, внесенные в ОбъектОбработка, не попадут обратно в форму автоматически — для этого потребуется обратный вызов ЗначениеВРеквизитФормы(), но для простого вывода макета в этом нет необходимости. Для отработки подобных серверных вызовов подойдёт шаблон внешней печатной формы со встроенной отладкой из формы.
Разберем ситуацию, когда ваша обработка еще не открыта, и вам нужно программно получить из нее макет (например, из другой обработки или общего модуля). В этом случае мы используем менеджер ВнешниеОбработки и метод Создать(). Рассмотрим этот сценарий по шагам:
ВнешниеОбработки.Создать(ПутьКФайлу, Ложь), где второй параметр отключает безопасный режим (если это требуется для ваших задач).Посмотрим на пример кода:
ПутьКФайлу = "C:\MyReports\MyProcessing.epf";
ОбъектВнешняяОбр = ВнешниеОбработки.Создать(ПутьКФайлу, Ложь);
Макет = ОбъектВнешняяОбр.ПолучитьМакет("ИмяМакета");
Если же ваша обработка хранится в справочнике «Дополнительные отчеты и обработки» (БСП), процедура усложняется: вам нужно сначала выгрузить двоичные данные файла из хранилища во временный файл, а затем вызвать ВнешниеОбработки.Создать().
Проанализируем архитектурный подход. Хорошим тоном в разработке на 1С считается вынос логики формирования отчета или обработки данных в Модуль объекта. Это делает код более универсальным и упрощает работу с контекстом. В качестве готового образца такой архитектуры можно использовать пример внешней печатной формы для актуальных версий БСП.
Если вы создадите в модуле объекта экспортную процедуру (например, СформироватьТабДок()), то внутри неё вам не понадобятся никакие преобразования. Вы сможете обращаться к макету напрямую через ключевое слово ЭтотОбъект или просто по имени метода:
// В модуле ОБЪЕКТА
Процедура СформироватьТабДок(ТабДок) Экспорт
Макет = ПолучитьМакет("Макет"); // Работает напрямую
// ... логика вывода ...
КонецПроцедуры
// В модуле ФОРМЫ
&НаСервере
Процедура КомандаСформироватьНаСервере()
ОбъектОбработка = РеквизитФормыВЗначение("Объект");
ОбъектОбработка.СформироватьТабДок(Результат); // Результат - реквизит формы типа ТабличныйДокумент
КонецПроцедуры
Выясним причину возможных замедлений. При использовании РеквизитФормыВЗначение система создает новый экземпляр объекта в оперативной памяти сервера. Если ваша процедура вызывается очень часто (например, в цикле), это может привести к избыточному потреблению ресурсов.
Рекомендации по оптимизации:
ПолучитьМакет() внутри циклов перебора строк результата запроса.Печать(), где макет доступен без лишних манипуляций.Стоит упомянуть и профили безопасности. Если внешняя обработка запускается в безопасном режиме (что часто случается при загрузке через справочник дополнительных обработок), доступ к методу ПолучитьМакет() обычно сохраняется. Однако, если макет содержит внедренные ActiveX компоненты или специфические внешние объекты, система может заблокировать их инициализацию. В таких случаях убедитесь, что обработка зарегистрирована с необходимыми разрешениями в профиле безопасности информационной базы.
Подведем итог: главная ошибка кроется в попытке обратиться к файлу на диске через менеджер метаданных. Используя РеквизитФормыВЗначение("Объект"), вы переключаетесь на «настоящий» объект обработки и получаете полный доступ ко всем его внутренним ресурсам, включая макеты, параметры и экспортные функции.