В практике разработки на платформе 1С:Предприятие 8 часто возникает задача автоматической рассылки отчетов. Например, каждую неделю руководству необходимо отправлять актуальные лимиты расхода денежных средств в формате Excel. Поскольку регламентные задания выполняются в фоновом режиме на сервере, у них полностью отсутствует интерфейс (клиентский контекст). Это означает, что мы не можем использовать стандартные формы отчетов и интерактивные методы работы с ними. Для администрирования списка адресатов при решении этой задачи пригодится инструмент управления получателями рассылок отчетов.
В данной статье мы подробно разберем, как программно запустить отчет на базе Системы компоновки данных (СКД), загрузить конкретный пользовательский вариант настроек, передать нужные параметры и сохранить результат в файл без открытия формы.
Основная ошибка начинающих разработчиков при попытке запустить отчет из фонового задания — использование методов контекста формы. Например, метод УстановитьТекущийВариант() доступен только в модуле формы отчета на клиенте. Попытка вызвать его на сервере в модуле обработки или общего модуля приведет к ошибке компиляции: «Процедура или функция с указанным именем не определена».
Для выполнения отчета в фоновом режиме нам необходимо полностью воспроизвести весь цикл компоновки данных программным путем: от получения схемы до вывода готового документа. Сделать это нужно исключительно средствами серверного программного кода.
---
По умолчанию СКД использует настройки, заданные в конфигураторе (так называемые настройки по умолчанию). Если нам нужно применить конкретный пользовательский вариант настроек (например, «Лимиты расхода денежных средств - БЕЗ ДЕПОЗИТА И ВАЛЮТЫ»), нам необходимо извлечь их из системного хранилища вариантов отчетов.
В платформе 1С для работы с вариантами предусмотрен объект ХранилищеВариантовОтчетов. Попытка перебрать его настройки с помощью метода Выбрать() вызовет критическую ошибку, так как этого метода у менеджера хранилища настроек не существует. Вместо этого мы должны использовать метод ПолучитьСписок(), передав в него полное имя нашего отчета.
Рассмотрим правильный алгоритм поиска и загрузки настроек варианта по его представлению (имени):
// Полное имя отчета в метаданных обязательно указывается с префиксом "Отчет."
ИмяОтчета = "Отчет.ЛимитыРасходаДенежныхСредств";
// Получаем список всех доступных вариантов для данного отчета
СписокВариантов = ХранилищеВариантовОтчетов.ПолучитьСписок(ИмяОтчета);
НастройкиВарианта = Неопределено;
Для Каждого Вариант Из СписокВариантов Цикл
Если Вариант.Представление = "Лимиты расхода денежных средств - БЕЗ ДЕПОЗИТА И ВАЛЮТЫ" Тогда
// Загружаем настройки по уникальному ключу, который хранится в свойстве Значение
НастройкиВарианта = ХранилищеВариантовОтчетов.Загрузить(ИмяОтчета, Вариант.Значение);
Прервать;
КонецЕсли;
КонецЦикла;
Если НастройкиВарианта = Неопределено Тогда
ВызватьИсключение "Не найден указанный вариант отчета в хранилище вариантов!";
КонецЕсли;
Если ваша конфигурация построена на базе Библиотеки Стандартных Подсистем (БСП), задача упрощается. В БСП все варианты отчетов регистрируются в специальном справочнике ВариантыОтчетов. Мы можем быстро получить ключ нужного варианта с помощью простого запроса или метода поиска:
СсылкаНаВариант = Справочники.ВариантыОтчетов.НайтиПоНаименованию("Лимиты расхода денежных средств - БЕЗ ДЕПОЗИТА И ВАЛЮТЫ");
Если ЗначениеЗаполнено(СсылкаНаВариант) Тогда
КлючВарианта = СсылкаНаВариант.КлючВарианта;
НастройкиВарианта = ХранилищеВариантовОтчетов.Загрузить("Отчет.ЛимитыРасходаДенежныхСредств", КлючВарианта);
Иначе
// Если вариант не найден в БСП, берем структуру по умолчанию
СхемаКомпоновки = Отчеты.ЛимитыРасходаДенежныхСредств.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
НастройкиВарианта = СхемаКомпоновки.НастройкиПоУмолчанию;
КонецЕсли;
---
Часто разработчики пытаются изменять значения параметров непосредственно в уже сгенерированном объекте МакетКомпоновки.ЗначенияПараметров. Это архитектурно неверный подход (антипаттерн). Если изменять параметры в самом макете, система компоновки не сможет правильно оптимизировать SQL-запрос и применить параметры к виртуальным таблицам и вложенным схемам.
Правильный способ — устанавливать значения параметров в объекте Настройки (тип НастройкиКомпоновкиДанных) до момента выполнения компоновки макета. Давайте посмотрим, как это реализовать:
// Устанавливаем параметры в настройках компоновки
НастройкиВарианта.ПараметрыДанных.УстановитьЗначениеПараметра("НачалоПериода", НачалоМесяца(ТекущаяДата()));
НастройкиВарианта.ПараметрыДанных.УстановитьЗначениеПараметра("КонецПериода", КонецМесяца(ТекущаяДата()));
// Если параметр может отсутствовать в схеме, желательно сделать проверку его существования
ПараметрХозОперация = НастройкиВарианта.ПараметрыДанных.Элементы.Найти("ХозяйственнаяОперация");
Если ПараметрХозОперация <> Неопределено Тогда
ПараметрХозОперация.Значение = Перечисления.ХозяйственныеОперации.ПустаяСсылка;
ПараметрХозОперация.Использование = Истина;
КонецЕсли;
---
При попытке программно наложить отборы на компоновку часто возникает ошибка: «Ошибка компоновки макета. Поле не найдено "[Имя Поля]"». Выясним причину этой проблемы.
В СКД у каждого поля есть системное имя (путь к данным) и синоним (заголовок, который видит пользователь в режиме предприятия). Например, в интерфейсе поле может называться "Статья ДДС" (с пробелом), но его реальный путь к данным в схеме компоновки — "СтатьяДвиженияДенежныхСредств". При программной установке левого значения отбора мы всегда обязаны указывать только системный путь к данным (без пробелов, спецсимволов и в строгом соответствии с регистром).
Давайте разберем правильный код добавления программного отбора по списку значений:
// Очищаем существующие отборы, если это необходимо
НастройкиВарианта.Отбор.Элементы.Очистить();
// Добавляем новый элемент отбора
НовыйОтбор = НастройкиВарианта.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
// Важно: передаем точный путь к данным поля из схемы компоновки (без пробелов!)
НовыйОтбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("СтатьяДвиженияДенежныхСредств");
НовыйОтбор.Использование = Истина;
НовыйОтбор.ВидСравнения = ВидСравненияКомпоновкиДанных.НеВСписке;
// Формируем список исключаемых статей
СписокИсключений = Новый СписокЗначений;
СписокИсключений.Добавить(Справочники.СтатьиДвиженияДенежныхСредств.НайтиПоНаименованию("Покупка валюты"));
СписокИсключений.Добавить(Справочники.СтатьиДвиженияДенежныхСредств.НайтиПоНаименованию("Выплата депозита"));
НовыйОтбор.ПравоеЗначение = СписокИсключений;
---
Теперь объединим все шаги в единую процедуру, которую можно разместить в модуле внешней обработки или общем серверном модуле для вызова по регламентному заданию. Мы загрузим схему, применим настройки нашего варианта, установим параметры, выполним компоновку и сохраним полученный результат в формате XLS.
Процедура ВыполнитьРассылкуОтчетаЛимиты() Экспорт
// 1. Получаем основную схему компоновки из макета отчета
СхемаКомпоновкиДанных = Отчеты.ЛимитыРасходаДенежныхСредств.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
// 2. Пытаемся загрузить настройки конкретного пользовательского варианта
ИмяОтчета = "Отчет.ЛимитыРасходаДенежныхСредств";
ИмяНужногоВарианта = "Лимиты расхода денежных средств - БЕЗ ДЕПОЗИТА И ВАЛЮТЫ";
Настройки = Неопределено;
СписокВариантов = ХранилищеВариантовОтчетов.ПолучитьСписок(ИмяОтчета);
Для Каждого Вариант Из СписокВариантов Цикл
Если Вариант.Представление = ИмяНужногоВарианта Тогда
Настройки = ХранилищеВариантовОтчетов.Загрузить(ИмяОтчета, Вариант.Значение);
Прервать;
КонецЕсли;
КонецЦикла;
// Если вариант не найден в хранилище, берем настройки по умолчанию
Если Настройки = Неопределено Тогда
Настройки = СхемаКомпоновкиДанных.НастройкиПоУмолчанию;
КонецЕсли;
// 3. Заполняем параметры периода
Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("НачалоПериода", НачалоМесяца(ТекущаяДата()));
Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("КонецПериода", КонецМесяца(ТекущаяДата()));
// 4. Подготавливаем объекты для компоновки макета
ДанныеРасшифровки = Новый ДанныеРасшифровкиКомпоновкиДанных;
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
// Выполняем компоновку схемы на основе подготовленных настроек
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);
// 5. Инициализируем процессор компоновки данных
ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки);
// 6. Выводим результат компоновки в новый табличный документ
РезультатТД = Новый ТабличныйДокумент;
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(РезультатТД);
ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных);
// 7. Сохраняем итоговый отчет в файл на диске сервера
ПутьКФайлу = "C:\Reports\LimitsReport.xls";
РезультатТД.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.XLS);
// Здесь можно вызвать функцию отправки полученного файла по электронной почте
// ОтправитьПисьмоСОтчетом(ПутьКФайлу);
КонецПроцедуры
Используя данный шаблон, мы можем гибко автоматизировать формирование любых отчетов в системе. Код полностью автономен, не зависит от наличия открытых окон пользователя и идеально подходит для работы в составе фоновых задач и регламентных рассылок. Если же вы хотите избежать изменения конфигурации, для аналогичных задач подойдёт типовой механизм БСП для запуска регламентных заданий с сохраненными настройками.