Как разместить внешний отчет (.erf) в подменю печати документов или справочников в 1С:Предприятии?

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

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

В чем заключается основная проблема?

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

"Вид обработки, указанный в сведениях о внешней обработке, не соответствует ее расширению."

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

  1. Файлы .erf (внешние отчеты): Эти файлы предназначены для создания полноценных отчетов. Отчеты обычно имеют собственную форму с параметрами, возможностью настройки отбора, группировок, формирования диаграмм и т.д. Они вызываются, как правило, из подменю "Отчеты" или "Дополнительные отчеты" и формируются после нажатия кнопки "Сформировать".
  2. Файлы .epf (внешние печатные формы и обработки): Эти файлы используются для формирования печатных форм документов или элементов справочников, а также для реализации произвольных обработок. Печатные формы обычно не имеют сложной формы настроек; их задача — получить данные из объекта-источника (например, документа реализации) и вывести их в табличный документ. Их вызов происходит через подменю "Печать", и формирование начинается сразу после выбора пункта.

Модуль УправлениеПечатью в БСП предназначен для работы с печатными формами, тогда как ДополнительныеОтчетыИОбработки обеспечивает механизм регистрации обоих видов внешних файлов, но с учетом их типа и расширения.

Функция СведенияОВнешнейОбработке() для печатных форм

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


Функция СведенияОВнешнейОбработке() Экспорт
    
    ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке();
    ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиПечатнаяФорма();
    ПараметрыРегистрации.Наименование = НСтр("ru='Корректировочный акт'"); // Имя, под которым обработка будет зарегистрирована в справочнике внешних обработок
    ПараметрыРегистрации.БезопасныйРежим = Ложь; // Установка режима безопасности
    ПараметрыРегистрации.Версия = "25.08.2021"; // Версия обработки
    ПараметрыРегистрации.Информация = НСтр("ru='" + ЭтотОбъект.Метаданные().Комментарий + "'"); // Дополнительная информация
    
    // Назначение: указываем, для каких объектов будет доступна печатная форма
    // Например, для документа "КорректировкаРеализации"
    ПараметрыРегистрации.Назначение.Добавить("Документ.КорректировкаРеализации");
    
    // Описываем команду, которая будет отображаться в подменю "Печать"
    Команда = ПараметрыРегистрации.Команды.Добавить();
    Команда.Идентификатор = "ПФ_КорректировочныйАкт"; // Уникальный идентификатор команды
    Команда.Представление = "Корректировочный акт"; // Текст, отображаемый в подменю
    Команда.ПоказыватьОповещение = Ложь; // Не показывать оповещение о формировании
    // Тип команды: вызов серверного метода, который формирует печатную форму
    Команда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовСерверногоМетода();
    
    Возврат ПараметрыРегистрации;
    
КонецФункции

Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
    
    // Проверяем, нужно ли печатать именно нашу форму по ее идентификатору
    Если УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, "ПФ_КорректировочныйАкт") Тогда
        // Выводим сформированный табличный документ в коллекцию печатных форм
        УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(
            КоллекцияПечатныхФорм,
            "ПФ_КорректировочныйАкт", // Идентификатор команды
            "Корректировочный акт", // Заголовок печатной формы
            // Вызов вашей функции, которая непосредственно формирует табличный документ
            ПечатьКорректировочногоАкта(МассивОбъектов, ОбъектыПечати)
        );
    КонецЕсли;
    
КонецПроцедуры

В приведенном примере мы видим, как регистрируется печатная форма. Важные моменты:

  1. ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиПечатнаяФорма(); — это ключевой параметр для определения типа.
  2. ПараметрыРегистрации.Назначение.Добавить("Документ.КорректировкаРеализации"); — определяет, к каким объектам будет привязана эта печатная форма.
  3. Команда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовСерверногоМетода(); — указывает, что при выборе команды будет вызван экспортный метод обработки (обычно Печать()).
  4. Процедура Печать() — это точка входа, которая будет вызвана системой при выборе команды печати (инструменты отладки внешних печатных форм помогут быстро найти ошибки в этой процедуре). В ней вы должны сформировать табличный документ и добавить его в КоллекциюПечатныхФорм.

Варианты решения проблемы (без полной переделки отчета с нуля)

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

1. Изменение расширения файла отчета с .erf на .epf

Это самый простой, но не всегда самый правильный с архитектурной точки зрения, способ. Мы просто меняем расширение файла вашего отчета. Рассмотрим, как это сделать:

  1. Откройте ваш внешний отчет (файл .erf) в конфигураторе 1С.
  2. Сохраните его как файл с расширением .epf (например, "МояПечатнаяФорма.epf").
  3. Внутри этого файла .epf мы корректируем функцию СведенияОВнешнейОбработке(), чтобы она регистрировала обработку как печатную форму:
    
    Функция СведенияОВнешнейОбработке() Экспорт
        ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке();
        ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиПечатнаяФорма();
        // ... остальные параметры ...
        // Указываем объекты, для которых будет доступна печать
        ПараметрыРегистрации.Назначение.Добавить("Документ.ВашДокумент"); 
        // ... описываем команду ...
        Команда = ПараметрыРегистрации.Команды.Добавить();
        Команда.Идентификатор = "ПФ_МойОтчет";
        Команда.Представление = "Мой отчет как печатная форма";
        Команда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовСерверногоМетода();
        Возврат ПараметрыРегистрации;
    КонецФункции
    
  4. Далее, если ваш отчет изначально формировал табличный документ через свою основную форму, нам потребуется выделить логику формирования табличного документа в отдельную экспортную функцию (например, СформироватьТабличныйДокумент()) или напрямую использовать ее в процедуре Печать().
  5. Реализуем процедуру Печать(), как показано в примере выше, вызывая вашу функцию формирования табличного документа.
    
    Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
        Если УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, "ПФ_МойОтчет") Тогда
            ТабличныйДокументОтчета = ПолучитьТабличныйДокументИзОтчета(МассивОбъектов); // Ваша функция
            УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(
                КоллекцияПечатныхФорм,
                "ПФ_МойОтчет",
                "Мой отчет как печатная форма",
                ТабличныйДокументОтчета
            );
        КонецЕсли;
    КонецПроцедуры
    

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

2. Создание "обертки" в виде внешней печатной формы (.epf) для вашего отчета (.erf)

Этот подход является более корректным с точки зрения архитектуры. Мы сохраняем ваш отчет .erf в его исходном виде, а для вывода его результата в подменю "Печать" создаем отдельную, минималистичную внешнюю печатную форму .epf, которая будет вызывать функциональность вашего .erf. Разберем шаги:

  1. Подготовка отчета (.erf):

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

    
    // В модуле объекта вашего внешнего отчета (.erf)
    Функция ПолучитьТабличныйДокументОтчета(МассивОбъектов) Экспорт
        // Здесь содержится вся логика формирования отчета
        // Получение данных из МассивОбъектов
        // Запросы, компоновка, заполнение макета
        ТабличныйДокумент = Новый ТабличныйДокумент;
        // ... ваш код по формированию табличного документа ...
        Возврат ТабличныйДокумент;
    КонецФункции
    
  2. Создание внешней печатной формы (.epf):

    Создайте новый файл внешней обработки с расширением .epf (например, "ОберткаДляОтчета.epf").

  3. Регистрация "обертки" как печатной формы:

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

  4. Реализация процедуры Печать() в "обертке" (.epf):

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

    Вариант 2.1: Копирование логики. Мы просто переносим экспортную функцию ПолучитьТабличныйДокументОтчета() из .erf в модуль объекта вашей .epf.

    Вариант 2.2: Вызов через ДополнительныеОтчетыИОбработки (если .erf зарегистрирован). Если ваш .erf уже зарегистрирован в системе как дополнительный отчет (с ВидОбработкиДополнительныйОтчет()), мы можем попробовать вызвать его экспортные методы через ДополнительныеОтчетыИОбработки.ВыполнитьКомандуОбработки() или аналогичные механизмы. Однако это сложнее и не всегда оправдано для простой печатной формы.

    Наиболее практичным будет Вариант 2.1, если логика формирования отчета не слишком объемна и не требует сохранения интерактивной формы .erf. Если же .erf сложный и интерактивный, то копирование кода может быть нежелательным. В этом случае, мы рассматриваем третий вариант.

Преимущества: Четкое разделение ответственности между отчетом и печатной формой, сохранение исходного .erf. Недостатки: Требует дублирования кода или более сложной логики вызова между обработками.

3. Использование механизма БСП для вызова отчета из печатной формы (оптимизированный вариант "обертки")

Этот подход является развитием предыдущего и предполагает, что основная логика формирования табличного документа в вашем .erf может быть легко выделена в отдельную переиспользуемую функцию. Мы создаем .epf, которая будет вызывать эту логику.

  1. Рефакторинг отчета (.erf):

    Выделяем всю логику формирования табличного документа (запросы, компоновка, заполнение макета) в отдельную экспортную функцию в модуле вашего отчета .erf. Назовем ее, например, СформироватьТабличныйДокументПоДанным(МассивОбъектов, Параметры). Это сделает ваш отчет более модульным.

    
    // В модуле объекта вашего внешнего отчета (.erf)
    Функция СформироватьТабличныйДокументПоДанным(МассивОбъектов, Параметры) Экспорт
        // ... логика формирования табличного документа ...
        Возврат ТабличныйДокумент;
    КонецФункции
    
  2. Создание внешней печатной формы (.epf):

    Создаем новый файл .epf.

  3. Регистрация .epf как печатной формы:

    В .epf реализуем функцию СведенияОВнешнейОбработке(), как описано ранее, с ВидОбработкиПечатнаяФорма().

  4. Реализация процедуры Печать() в .epf:

    Теперь в процедуре Печать() нашей .epf мы программно загружаем наш .erf и вызываем его экспортную функцию. Это требует, чтобы .erf был доступен (например, лежал рядом или был загружен через справочник "Дополнительные отчеты и обработки").

    
    Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
        Если УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, "ПФ_МойОтчет") Тогда
                    
            // 1. Получаем путь к вашему внешнему отчету (.erf)
            // Если отчет уже зарегистрирован как дополнительный, можно получить его из справочника
            // Иначе, путь должен быть известен или передан параметром
            // Для упрощения примера, предположим, что файл .erf лежит рядом
                    
            ПутьКФайлуОтчета = ОбщегоНазначенияКлиентСервер.ПолучитьПутьКФайлуВременногоХранилища(
                ЭтотОбъект.ИмяФайлаВременногоХранилища + ".erf" // Предполагаем, что .erf рядом с .epf
            );
                    
            // Или, если .erf зарегистрирован как доп. отчет:
            // ДополнительныйОтчетСсылка = ДополнительныеОтчетыИОбработки.НайтиДополнительныйОтчетПоИдентификатору("ВашИдентификаторОтчета");
            // Если ДополнительныйОтчетСсылка.Пустая() Тогда
            //    // Обработка ошибки
            // КонецЕсли;
            // ПутьКФайлуОтчета = ДополнительныеОтчетыИОбработки.ПолучитьПутьКФайлуВременногоХранилища(ДополнительныйОтчетСсылка);
                    
            // 2. Создаем временный объект внешней обработки для отчета
            Попытка
                ВнешнийОтчетОбъект = ВнешниеОтчеты.Создать(ПутьКФайлуОтчета);
            Исключение
                ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Не удалось загрузить внешний отчет: " + ОписаниеОшибки());
                Возврат;
            КонецПопытки;
                    
            Если ВнешнийОтчетОбъект = Неопределено Тогда
                ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Внешний отчет не найден или не загружен.");
                Возврат;
            КонецЕсли;
                    
            // 3. Вызываем экспортную функцию из загруженного отчета
            ПараметрыДляОтчета = Новый Соответствие;
            // Заполняем параметры, необходимые для формирования отчета
            // Например: ПараметрыДляОтчета.Вставить("ДатаНачала", ТекущаяДата());
                    
            ТабличныйДокументОтчета = ВнешнийОтчетОбъект.СформироватьТабличныйДокументПоДанным(МассивОбъектов, ПараметрыДляОтчета);
                    
            Если ТабличныйДокументОтчета <> Неопределено Тогда
                УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(
                    КоллекцияПечатныхФорм,
                    "ПФ_МойОтчет",
                    "Мой отчет как печатная форма",
                    ТабличныйДокументОтчета
                );
            Иначе
                ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Отчет не смог сформировать табличный документ.");
            КонецЕсли;
        КонецЕсли;
    КонецПроцедуры
    

Преимущества: Полное разделение логики, отчет остается интерактивным .erf, а .epf служит тонкой "прослойкой" для вызова. Это наиболее гибкий и масштабируемый подход. Недостатки: Требует аккуратной организации кода, убедитесь, что ваш .erf всегда доступен или корректно загружается. Возможны нюансы с безопасным режимом и областями выполнения кода.

Важные моменты при работе с процедурой Печать()

Независимо от выбранного способа, процедура Печать() является центральной для формирования печатной формы. Мы хотим выделить основные аспекты ее работы:

  1. Параметры:
    • МассивОбъектов: Массив ссылок на объекты (документы, элементы справочников), для которых требуется сформировать печатную форму.
    • КоллекцияПечатныхФорм: Коллекция, в которую необходимо добавить сформированные табличные документы.
    • ОбъектыПечати: Табличная часть со списком объектов, для которых требуется сформировать печатные формы, и их макетами.
    • ПараметрыВывода: Структура с параметрами вывода (например, требуется ли предпросмотр, отправка по почте и т.д.).
  2. Проверка необходимости печати:

    Всегда используйте функцию УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, "ВашИдентификаторКоманды"). Это позволяет избежать избыточных вычислений, если пользователь выбрал печать только определенных макетов или ваша форма не была запрошена.

  3. Формирование табличного документа:

    Ваша основная задача — получить или сформировать объект ТабличныйДокумент, который содержит готовую печатную форму. Это может быть результат запросов, заполнение областей макета и т.д.

  4. Добавление в коллекцию:

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

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

← На главную