При разработке отчетов на базе Системы компоновки данных (СКД) программисты часто сталкиваются с ситуацией: в режиме «1С:Предприятие» отчет работает идеально, параметры заполняются автоматически через код в модуле. Однако, стоит попытаться вызвать этот же отчет программно (например, для автоматической рассылки или сохранения в файл из внешней обработки), как система выдает ошибку: «Параметр не заполнен». Проанализируем, почему это происходит, и разберем правильные методы инициализации параметров.
Разберем ситуацию, описанную в теме. Автор использует процедуру ПриКомпоновкеРезультата в модуле отчета для установки значения параметра &Период. Когда пользователь открывает отчет стандартным способом, платформа создает Объект отчета и вызывает это событие. Но когда мы пишем во внешней обработке следующий код:
СКД1 = Отчеты.Взаиморасчеты.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
Настройки1 = СКД1.НастройкиПоУмолчанию;
Мы совершаем типичную ошибку: мы обращаемся напрямую к Макету (XML-описанию схемы), минуя сам объект отчета. В этом случае процедура ПриКомпоновкеРезультата, написанная в модуле отчета, просто не выполняется. Платформа не создает экземпляр отчета, а значит, ваш программный код по установке параметров игнорируется.
Самый простой и надежный способ, который будет работать везде — и в интерфейсе, и в фоновых заданиях, и при программном вызове — это использование встроенных выражений СКД. Рассмотрим, как это настроить без написания кода в модулях:
Период.КонецПериода(ТекущаяДата(), "День").Такой подход гарантирует, что СКД сама вычислит значение параметра в момент компоновки макета, независимо от того, каким способом вызывается отчет. Для изучения практических вариантов настройки выражений и компоновки можно использовать примеры программной работы с СКД.
Если нам критично использовать именно код в модуле отчета (например, там сложная логика расчета параметров), нам нужно заставить платформу выполнить процедуру ПриКомпоновкеРезультата. Для этого необходимо создать объект отчета программно. Рассмотрим правильный алгоритм:
// Создаем объект отчета
ОтчетОбъект = Отчеты.Взаиморасчеты.Создать();
// Подготавливаем табличный документ для результата
ТабДок = Новый ТабличныйДокумент;
// Вызываем стандартный метод компоновки - именно он инициирует событие ПриКомпоновкеРезультата
ОтчетОбъект.СкомпоноватьРезультат(ТабДок);
// После этого ТабДок будет заполнен данными с учетом параметров из модуля
ТабДок.Записать("C:\Temp\report.xls", ТипФайлаТабличногоДокумента.XLS);
В этом случае 1С отработает полный цикл формирования отчета, включая выполнение всех процедур в модуле объекта.
Если мы формируем отчет «вручную» через ПроцессорКомпоновкиДанных (как это делал автор темы в Сообщении 4), нам нужно передать параметры непосредственно в КомпоновщикНастроек перед тем, как создавать макет компоновки. Разберем по шагам, как это сделать правильно:
Процедура СформироватьОтчетПрограммно()
ТабДок = Новый ТабличныйДокумент;
// Получаем схему
Схема = Отчеты.Взаиморасчеты.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
// Инициализируем компоновщик настроек
Компоновщик = Новый КомпоновщикНастроекКомпоновкиДанных;
Компоновщик.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(Схема));
Компоновщик.ЗагрузитьНастройки(Схема.НастройкиПоУмолчанию);
// Устанавливаем параметры программно
ПараметрПериод = Компоновщик.Настройки.ПараметрыДанных.Элементы.Найти("Период");
Если ПараметрПериод <> Неопределено Тогда
ПараметрПериод.Значение = КонецДня(ТекущаяДата());
ПараметрПериод.Использование = Истина;
КонецЕсли;
// Важно: работаем дальше с настройками из КОМПОНОВЩИКА, а не из СХЕМЫ
Настройки = Компоновщик.ПолучитьНастройки();
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, Настройки);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ТабДок);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
ТабДок.Показать();
КонецПроцедуры
Обратите внимание: крайне важно использовать метод Компоновщик.ПолучитьНастройки(). Он собирает воедино основные настройки, пользовательские настройки и те изменения, которые вы внесли программно. Если передать в КомпоновщикМакета.Выполнить() просто Схема.НастройкиПоУмолчанию, ваши программные правки параметров будут проигнорированы. Для упрощения и сокращения такого низкоуровневого кода компоновки подойдёт модуль-обёртка над объектной моделью СКД.
Проанализируем ситуацию с виртуальными таблицами (например, РегистрБухгалтерии.Хозрасчетный.Остатки). В запросе автора используется параметр &Период. Выясним важную деталь: СКД умеет автоматически сопоставлять стандартные параметры периодов с параметрами виртуальных таблиц.
Если вы вручную добавляете параметр с именем Период в схему, убедитесь, что его тип совпадает с ожидаемым типом виртуальной таблицы (обычно это Дата или СтандартныйПериод). Если СКД «не понимает» параметр, проверьте вкладку «Связи параметров» и убедитесь, что параметр запроса действительно связан с параметром компоновки.
Выясним основные правила, которые помогут избежать ошибок при заполнении параметров СКД:
Создать() и используйте СкомпоноватьРезультат(), если логика завязана на модуле.КомпоновщикНастроек.Настройки и не забывайте устанавливать свойство Использование = Истина.Соблюдение этих архитектурных принципов 1С позволит вашим отчетам корректно работать в любых условиях — от ручного формирования бухгалтером до регламентного задания на сервере.