В процессе автоматизации бизнес-процессов часто возникает задача регулярного формирования различных отчетов и их сохранения на диск или отправки по электронной почте. Это позволяет руководству и ответственным сотрудникам получать актуальные данные в удобном формате (например, Excel или PDF) без необходимости заходить в программу 1С и формировать отчеты вручную.
В этой статье мы подробно разберем, как реализовать автоматическое сохранение отчета, построенного на базе системы компоновки данных (СКД). Мы проанализируем типичные ошибки, с которыми сталкиваются разработчики при решении этой задачи, изучим правильные методы программной компоновки и рассмотрим наиболее надежные архитектурные подходы.
На первый взгляд задача кажется тривиальной. В модуле объекта отчета существует предопределенное событие ПриКомпоновкеРезультата. Логично предположить, что достаточно написать одну строчку кода, чтобы сохранить результат. Давайте посмотрим на типичную ошибку, которую часто совершают начинающие разработчики:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
// Попытка записать документ в файл
ДокументРезультат.Записать("C:\Reports\Отчет.xlsx", ТипФайлаТабличногоДокумента.XLSX);
КонецПроцедуры
При запуске такого кода отчет будет сформирован на экране, файл на диске действительно появится, однако при попытке его открыть мы обнаружим, что он абсолютно пуст. Выясним причину такого поведения платформы.
Дело в том, что в момент вызова обработчика события ПриКомпоновкеРезультата сам процесс построения отчета еще даже не начался. Параметр ДокументРезультат передается в процедуру пустым. Платформа только готовится вывести в него данные. Соответственно, вызывая метод Записать в самом начале процедуры, мы сохраняем еще незаполненный табличный документ.
Чтобы сохранить уже заполненный данными документ, нам необходимо полностью взять управление процессом компоновки в свои руки. Для этого мы должны отключить стандартный механизм вывода платформы, самостоятельно инициализировать все промежуточные объекты СКД, вывести результат в табличный документ и только после этого сохранить его на диск.
Рассмотрим подробнее программный код, который решает эту задачу внутри модуля объекта отчета:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
// 1. Отключаем стандартный вывод отчета платформой
СтандартнаяОбработка = Ложь;
// 2. Получаем текущие настройки отчета (пользовательские настройки)
НастройкиОтчета = КомпоновщикНастроек.ПолучитьНастройки();
// 3. Инициализируем компоновщик макета
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
// Создаем макет компоновки с использованием нашей схемы и настроек
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, НастройкиОтчета, ДанныеРасшифровки);
// 4. Инициализируем процессор компоновки данных
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);
// 5. Создаем процессор вывода и связываем его с результирующим табличным документом
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
// Выводим результат компоновки в табличный документ
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
// 6. Теперь, когда ДокументРезультат полностью заполнен, мы можем его сохранить
ПутьКФайлу = "E:\backup\images\ОтчетОстатки.xlsx";
Попытка
ДокументРезультат.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.XLSX);
Исключение
ЗаписьЖурналаРегистрации("СохранениеОтчета", УровеньЖурналаРегистрации.Ошибка, , ,
"Не удалось сохранить отчет. Ошибка: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Давайте разберем по шагам, что происходит в этом коде:
СтандартнаяОбработка = Ложь сообщает платформе, что мы отказываемся от автоматического вывода и берем управление на себя. Если этого не сделать, отчет сформируется дважды или вызовет конфликт блокировок.ПолучитьНастройки() компоновщика. Это крайне важно, так как именно здесь содержатся все отборы, параметры и группировки, которые пользователь указал на форме.КомпоновщикМакетаКомпоновкиДанных соединяет схему компоновки (структуру запросов) и настройки в один готовый макет.ПроцессорКомпоновкиДанных осуществляет непосредственный выборку данных из базы данных на основе подготовленного макета.ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент последовательно выводит полученные выборки в итоговую таблицу.Записать вызывается только тогда, когда все данные выгружены. Мы обернули его в блок Попытка...Исключение, чтобы защитить систему от аварийного завершения в случае сетевых сбоев или проблем с правами доступа.Часто при тестировании механизма автосохранения разработчики сталкиваются с ошибками вида: "Ошибка доступа к файлу 'C:\Users\User\Desktop\отчет.xlsx'". Проанализируем причину ее возникновения.
Если автоматическое сохранение планируется запускать по расписанию, то этот процесс будет выполняться в контексте Регламентного задания. Регламентные задания работают на стороне сервера 1С под управлением специальной системной учетной записи (например, USR1CV8).
Для стабильной работы системы необходимо соблюдать следующие правила адресации файлов:
C:\TempReports\) и предоставьте пользователю, от имени которого запущен сервер 1С, полные права (чтение, запись, изменение) на этот каталог.\\ИмяСервера\ИмяПапки\Отчет.xlsx. Предварительно убедитесь, что служба сервера 1С имеет доступ к сетевому ресурсу.В некоторых обсуждениях предлагается открывать форму отчета программно через Форма.Открыть() и имитировать интерактивное нажатие кнопок. Это в корне неверный подход!
Регламентные задания выполняются в неинтерактивном режиме на сервере, где графический интерфейс полностью отсутствует. Попытка открыть форму приведет к критической ошибке выполнения программы. Для работы по расписанию отчет должен формироваться полностью программно.
Создадим процедуру в общем серверном модуле (с установленным флагом "Сервер" и без флагов "Клиент"), которую затем подключим к регламентному заданию:
Процедура СформироватьИСохранитьОтчетСервер() Экспорт
// Инициализируем объект отчета без открытия его формы
ИмяОтчета = "ОстаткиНашихИПоставщиков";
ОтчетОбъект = Отчеты[ИмяОтчета].Создать();
// Настраиваем схему компоновки
СхемаКД = ОтчетОбъект.СхемаКомпоновкиДанных;
Настройки = ОтчетОбъект.КомпоновщикНастроек.ПолучитьНастройки();
// При необходимости здесь можно программно установить параметры отчета
// Пример установки даты окончания периода:
ПараметрПериод = Настройки.ПараметрыДанных.Элементы.Найти("КонецПериода");
Если ПараметрПериод <> Неопределено Тогда
ПараметрПериод.Значение = ТекущаяДата();
ПараметрПериод.Использование = Истина;
КонецЕсли;
// Инициализируем программную компоновку
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
ДанныеРасшифровки = Новый ДанныеРасшифровкиКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКД, Настройки, ДанныеРасшифровки);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);
// Формируем результирующий табличный документ
ТабДок = Новый ТабличныйДокумент;
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ТабДок);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
// Формируем уникальное имя файла с датой и временем создания
ИмяФайла = "C:\TempReports\Report_" + Формат(ТекущаяДата(), "ДФ=yyyyMMdd_HHmmss") + ".xlsx";
// Записываем результат на диск
ТабДок.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.XLSX);
КонецПроцедуры
Этот код абсолютно автономен, не зависит от интерфейса клиентского приложения, не требует открытия форм и может без проблем выполняться сервером 1С в фоновом режиме в любое назначенное время.
Если вы работаете в современной типовой конфигурации 1С (такой как "1С:Бухгалтерия", "1С:Управление торговлей", "1С:ERP" или "1С:Комплексная автоматизация"), то писать программный код для решения этой задачи вовсе не обязательно. В состав данных конфигураций уже включена Библиотека стандартных подсистем (БСП), которая содержит мощный готовый инструмент для автоматизации работы с отчетами.
Выполним настройку автосохранения по шагам с помощью типового функционала:
Использование механизма БСП является наиболее предпочтительным и надежным способом в типовых конфигурациях. Оно существенно экономит время разработки, упрощает администрирование системы и гарантирует корректность выполнения операций обновления и резервного копирования данных.