Как программно открыть внешний отчет из модуля обычного приложения 1С?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

В процессе разработки и сопровождения конфигураций на платформе 1С:Предприятие (особенно классических решений на обычных формах, таких как УПП 1.3, КА 1.1 или УТ 10.3) часто возникает задача хранения внешних обработок и отчетов непосредственно в информационной базе. Обычно для этого используется специальный справочник (например, ВнешниеОбработки или ДополнительныеОтчетыИОбработки), где файлы отчетов хранятся в виде двоичных данных в реквизите с типом ХранилищеЗначения.

При попытке программно извлечь такой отчет из хранилища и открыть его форму "на лету" разработчики нередко сталкиваются со следующей ошибкой:


{МодульОбычногоПриложения(348)}: Ошибка при вызове метода контекста (ПолучитьФорму)
    Форма = Обработка.ПолучитьФорму("ФормаОтчета");
по причине:
Недопустимое значение параметра (параметр номер '1')

В рамках этой статьи мы подробно разберем, почему возникает данная ошибка, как правильно инициализировать внешние файлы разных типов, а также рассмотрим важные архитектурные нюансы, требования безопасности и лучшие практики работы с временными файлами в 1С.

Выясняем причину ошибки: Внешние обработки против Внешних отчетов

Давайте проанализируем исходный код, который вызвал затруднения у автора темы:


ВнешняяОбработка = Справочники.ВнешниеОбработки.НайтиПоКоду("УПП000374");
ДвоичныеДанные = ВнешняяОбработка.ХранилищеВнешнейОбработки.Получить();
ИмяФайла = ПолучитьИмяВременногоФайла("erf");
ДвоичныеДанные.Записать(ИмяФайла);

// Попытка 1: Сбой, возвращает Неопределено
Форма = ВнешниеОбработки.ПолучитьФорму(ИмяФайла); 
Форма.Открыть();

// Попытка 2 (закомментированная): Вылетает с ошибкой "Недопустимое значение параметра"
//Обраб = ВнешниеОбработки.Создать(ИмяФайла);
//Форма = Обраб.ПолучитьФорму("ФормаОтчета");
//Форма.Открыть();

Главная причина сбоя кроется в фундаментальном различии типов объектов платформы 1С. Обратите внимание на расширение временного файла — это .erf (External Report File, внешний отчет на базе системы компоновки данных или классического макета).

В платформе 1С для работы с внешними файлами существуют два разных менеджера объектов:

Когда мы передаем файл отчета (.erf) в метод ВнешниеОбработки.Создать() или пытаемся получить его форму через ВнешниеОбработки.ПолучитьФорму(), платформа не может корректно инициализировать объект обработки, так как структура файла отчета отличается от структуры обработки. В результате объект создается некорректно либо метод ПолучитьФорму() падает с ошибкой неверного параметра.

Правильное решение: Для файлов с расширением .erf необходимо использовать глобальный менеджер ВнешниеОтчеты.

Рассмотрим исправленный и рабочий вариант инициализации:


// Создаем объект внешнего отчета с помощью правильного менеджера
ОбъектОтчета = ВнешниеОтчеты.Создать(ИмяФайла);
// Получаем основную форму отчета и открываем ее
ФормаОтчета = ОбъектОтчета.ПолучитьФорму();
ФормаОтчета.Открыть();

---

Важные архитектурные нюансы и лучшие практики

Просто исправить менеджер на ВнешниеОтчеты недостаточно для промышленной эксплуатации решения. При работе в реальных многопользовательских базах данных необходимо предусмотреть очистку мусора, безопасность исполнения кода и совместимость интерфейсов. Разберем эти аспекты по шагам.

1. Очистка временных файлов (борьба с утечкой дискового пространства)

Метод ПолучитьИмяВременногоФайла("erf") создает уникальное имя файла в локальном каталоге временных файлов текущего пользователя операционной системы. Когда мы записываем туда двоичные данные методом ДвоичныеДанные.Записать(ИмяФайла), на диске создается физический файл.

Платформа 1С автоматически удаляет такие временные файлы только при штатном завершении сеанса пользователя. Если пользователи не закрывают программу сутками или отчеты генерируются очень часто (например, регламентными заданиями или в цикле обработки данных), папка Temp на диске быстро переполнится гигабайтами мусорных файлов, что приведет к снижению производительности системы или сбоям Windows.

Физический файл на диске нужен платформе только в момент вызова метода Создать(). Как только объект отчета загружен в оперативную память компьютера, файл на диске больше не нужен — его можно безболезненно удалить.

Рекомендуется использовать следующую безопасную конструкцию удаления файла сразу после инициализации отчета:


ИмяФайла = ПолучитьИмяВременногоФайла("erf");
ДвоичныеДанные.Записать(ИмяФайла);

// Инициализируем отчет в памяти
ОбъектОтчета = ВнешниеОтчеты.Создать(ИмяФайла);

// Сразу удаляем временный файл с диска
Попытка
    УдалитьФайлы(ИмяФайла);
Исключение
    // Записываем предупреждение в журнал регистрации, если файл по какой-то причине заблокирован ОС
    ЗаписьЖурналаРегистрации("ВнешниеОтчеты.ОчисткаВременныхФайлов", 
        УровеньЖурналаРегистрации.Предупреждение, , , 
        "Не удалось удалить временный файл: " + ИмяФайла + " Описание: " + ОписаниеОшибки());
КонецЕсли;

ФормаОтчета = ОбъектОтчета.ПолучитьФорму();
ФормаОтчета.Открыть();

2. Безопасный режим работы (Safe Mode)

Метод ВнешниеОтчеты.Создать() принимает второй, необязательный параметр: Создать(<ПолноеИмяФайла>, <БезопасныйРежим>).

Если второй параметр опущен или передан как Истина, отчет запускается в безопасном режиме платформы. В этом режиме отчету жестко запрещено:

Если ваш внешний отчет должен формировать, например, файлы выгрузки в Excel или обращаться к сторонним API, запуск в безопасном режиме вызовет ошибку нарушения прав доступа.

Если вы абсолютно уверены в источнике происхождения отчета и его коде, отключайте безопасный режим явным образом:


// Запуск внешнего отчета с полными правами (БезопасныйРежим = Ложь)
ОбъектОтчета = ВнешниеОтчеты.Создать(ИмяФайла, Ложь);

3. Специфика метода ПолучитьФорму() в обычном приложении

В обычном приложении вызов метода ПолучитьФорму() без параметров пытается получить форму, которая назначена в самом отчете в качестве Основной.

В гибридных конфигурациях (где могут параллельно существовать и обычные, и управляемые формы) разработчик мог назначить основной формой отчета управляемую форму (например, для использования отчета в тонком клиенте). При попытке вызвать этот метод в обычном приложении (толстом клиенте) платформа выдаст ошибку, так как обычный клиент не умеет напрямую рендерить управляемые интерфейсы без режима совместимости.

Чтобы гарантировать стабильность работы в обычном приложении, принудительно указывайте имя обычной формы отчета в качестве параметра, если она не установлена основной по умолчанию:


// Указываем имя конкретной обычной формы, созданной в отчете
ФормаОтчета = ОбъектОтчета.ПолучитьФорму("ФормаОтчетаОбычная");
Если ФормаОтчета <> Неопределено Тогда
    ФормаОтчета.Открыть();
КонецЕсли;

4. Перспективы перехода на управляемые формы и клиент-серверную архитектуру

Если в вашей организации планируется переход на управляемый интерфейс (например, переход с УПП 1.3 на ERP 2.5) или перенос баз в клиент-серверный вариант (на SQL), прямой код работы с файлами на клиенте перестанет работать. В управляемом приложении клиент не имеет прямого доступа к файловой системе сервера, а метод ВнешниеОтчеты.Создать() вообще недоступен на клиенте.

Схема запуска отчета в управляемом приложении кардинально меняется и выглядит следующим образом:

  1. Файл извлекается из справочника на сервере и помещается во временное хранилище платформы при помощи метода ПоместитьВоВременноеХранилище().
  2. На сервере вызывается метод регистрации отчета: ВнешниеОтчеты.Подключить(АдресХранилища, ИмяПодключения, БезопасныйРежим). Метод возвращает уникальное системное имя подключенного отчета.
  3. На клиенте открывается форма подключенного отчета через стандартную процедуру ОткрытьФорму("ВнешнийОтчет." + ИмяПодключения + ".Форма.ФормаОтчета").

5. Использование готовых механизмов БСП (Библиотеки стандартных подсистем)

Если ваша конфигурация содержит встроенную Библиотеку стандартных подсистем (БСП), крайне не рекомендуется писать «велосипеды» с ручной записью файлов во временные папки.

В составе БСП есть готовая подсистема "Дополнительные отчеты и обработки". Использование её программного интерфейса (API) гарантирует автоматическую очистку кэша, ведение журналов безопасности и совместимость как с обычными, так и с управляемыми формами. Открытие внешнего отчета через механизмы БСП сводится к простому вызову процедур общего модуля:


// Пример использования БСП для открытия дополнительного отчета
ПараметрыОткрытия = Новый Структура;
ПараметрыОткрытия.Вставить("ИсточникВызова", "МодульОбычногоПриложения");

// СсылкаНаВнешнийОтчет - это ссылка на элемент справочника дополнительных отчетов и обработок
ДополнительныеОтчетыИОбработкиКлиент.ВыполнитьОткрытиеФормыОбработки(СсылкаНаВнешнийОтчет, ПараметрыОткрытия);

Такой подход экономит время разработчика и страхует систему от появления труднодоступных ошибок при обновлениях платформы 1С.

← На главную