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