Как инициировать сохранение результата отчета СКД в файл при использовании стандартных форм БСП?

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

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

Анализ проблемы: почему стандартный подход не работает

Рассмотрим типичную ситуацию: в модуле объекта отчета в процедуре ПриКомпоновкеРезультата выполняется проверка параметра «Сохранить в файл». Если флаг установлен, разработчик использует ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений, получает таблицу, конвертирует ее в нужный формат и записывает на диск сервера. Однако процедура ПриКомпоновкеРезультата исполняется строго на сервере (или в фоновом задании). Методы платформы для передачи файла пользователю, такие как НачатьПолучениеФайлаССервера или ПолучитьФайл, требуют клиентского контекста.

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

Способ 1. Копирование общей формы отчета

Это самый быстрый и прямолинейный метод. Если нам нужно добавить специфическое поведение для конкретного отчета, мы можем отказаться от использования общей формы БСП в пользу локальной копии.

  1. Откроем дерево конфигурации, найдем ОбщиеФормы — ФормаОтчета (стандартная форма БСП).
  2. Скопируем эту форму непосредственно в наш объект Отчет.
  3. В модуле этой формы мы получаем полный контроль над клиентскими событиями. Разберем, как модифицировать процедуру формирования.

В модуле формы найдем обработчик команды Сформировать. Нам нужно дождаться окончания формирования отчета на сервере и проверить, был ли создан файл. Рассмотрим пример кода для клиентской части:


&НаКлиенте
Процедура ПослеЗавершенияФормирования(Результат, ДополнительныеПараметры) Экспорт
    
    Если Результат = "Выполнено" Тогда
        // Вызываем серверный метод, который проверит наличие файла во временном хранилище
        АдресФайла = ПолучитьАдресПодготовленногоФайлаНаСервере();
        
        Если ЗначениеЗаполнено(АдресФайла) Тогда
            ПараметрыПолучения = Новый ПараметрыПолученияФайла;
            ПараметрыПолучения.Заголовок = "Сохранение выгрузки отчета";
            
            НачатьПолучениеФайлаССервера(Новый ОписаниеОповещения("ЗавершениеПолученияФайла", ЭтотОбъект), АдресФайла, "Выгрузка.xlsx", ПараметрыПолучения);
        КонецЕсли;
    КонецЕсли;
    
КонецПроцедуры

Этот метод надежен, но имеет минус: при обновлении БСП вам придется вручную синхронизировать изменения в скопированной форме.

Способ 2. Использование расширения для перехвата событий БСП

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

Проанализируем шаги реализации через расширение:

  1. Создадим расширение и добавим в него общую форму ФормаОтчета.
  2. Создадим обработчик &После для метода СформироватьНаСервереЗавершение (или аналогичного в зависимости от версии БСП).
  3. В этом обработчике проверим настройки отчета. Если параметр сохранения в файл включен, извлечем адрес файла из временного хранилища.

Рассмотрим пример логики в модуле объекта отчета (в процедуре ПриКомпоновкеРезультата), которая подготавливает данные:


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

Способ 3. Программное добавление команды через интерфейс БСП

БСП предоставляет механизм ВариантыОтчетовПереопределяемый, который позволяет программно добавлять кнопки в подменю «Печать» или «Еще» формы отчета без изменения самой формы. Это наиболее архитектурно правильный подход, так как он разделяет формирование экранного представления и выгрузку данных.

Разберем, как это реализовать:

  1. В модуле ВариантыОтчетовПереопределяемый в процедуре НастроитьКомандыОтчетов добавим описание нашей команды выгрузки.
  2. Укажем обработчик команды, который будет располагаться в модуле менеджера отчета или в общей форме.
  3. В обработчике команды вызовем серверную функцию, которая выполнит компоновку СКД программно, сформирует файл и вернет его адрес.

Проанализируем пример серверной функции в модуле менеджера отчета:


Функция СформироватьФайлВыгрузки(ПараметрыОтчета) Экспорт
    
    ОтчетОбъект = Отчеты.НашОтчет.Создать();
    ОтчетОбъект.КомпоновщикНастроек.ЗагрузитьНастройки(ПараметрыОтчета.Настройки);
    
    // Программная компоновка (аналогично ПриКомпоновкеРезультата)
    // ... логика формирования ТабличногоДокумента ...
    
    Адрес = ПоместитьВоВременноеХранилище(ДанныеФайла);
    Возврат Адрес;
    
КонецФункции

На клиенте мы просто вызываем эту функцию и передаем результат в НачатьПолучениеФайлаССервера. Этот метод позволяет пользователю четко разделять действия: «Посмотреть отчет» и «Выгрузить файл для банка/налоговой».

Важные рекомендации при работе с СКД и файлами

1. Управление памятью. При выгрузке больших отчетов через ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений память сервера может быстро закончиться. Если данных очень много, рассмотрите возможность вывода напрямую в текстовый файл (CSV, XML) через ЗаписьТекста или ЗаписьXML, минуя промежуточные таблицы значений.

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

3. Временное хранилище. Всегда привязывайте адрес временного хранилища к уникальному идентификатору формы (ЭтаФорма.УникальныйИдентификатор), иначе данные могут быть удалены сборщиком мусора до того, как клиент успеет их запросить.

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

← На главную