В практике разработки на платформе 1С:Предприятие 8.3 часто возникает задача сформировать отчет на базе Системы компоновки данных (СКД) не стандартным способом, а программно. Особенно это актуально, когда данные для отчета подготавливаются сложным алгоритмом в модуле формы и выгружаются в Таблицу Значений, которую затем нужно «скормить» схеме компоновки. Рассмотрим подробно, как это реализовать, какие инструменты использовать и как избежать типичных ошибок, таких как «Поле не найдено».
Стандартный механизм СКД предполагает работу с запросами к базе данных. Однако бывают ситуации, когда:
ТабличныйДокумент на форме, не используя стандартную кнопку «Сформировать» основного отчета.Это классический и самый гибкий способ. Мы создаем в макете СКД набор данных типа Объект и связываем его с нашей Таблицей Значений. Разберем этот процесс по шагам.
Шаг 1. Подготовка макета СКД. В схеме компоновки данных создадим «Набор данных - объект». В поле «Имя объекта содержащего данные» укажем идентификатор, например, "ВнешниеДанныеТЗ". Важно: необходимо вручную добавить все поля, которые есть в вашей таблице значений, строго соблюдая типы данных и имена колонок.
Шаг 2. Программный код на сервере. Рассмотрим пример формирования отчета в процедуре модуля формы:
&НаСервере
Процедура СформироватьОтчетНаСервере()
// 1. Получаем данные в таблицу значений
Запрос = Новый Запрос("ВЫБРАТЬ Ссылка, Код, Наименование ИЗ Справочник.Номенклатура ГДЕ Ссылка В (&МассивСсылок)");
Запрос.УстановитьПараметр("МассивСсылок", СписокСсылок);
ТаблицаДанных = Запрос.Выполнить().Выгрузить();
// 2. Получаем схему из макета отчета
ОтчетОбъект = РеквизитФормыВЗначение("Отчет");
СхемаКомпоновкиДанных = ОтчетОбъект.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
// 3. Подготавливаем внешние наборы данных
ВнешниеНаборыДанных = Новый Структура;
ВнешниеНаборыДанных.Вставить("ВнешниеДанныеТЗ", ТаблицаДанных);
// 4. Получаем настройки
Настройки = Отчет.КомпоновщикНастроек.ПолучитьНастройки();
// 5. Инициализируем макет компоновки
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки);
// 6. Процессор компоновки данных
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных);
// 7. Вывод результата в табличный документ на форме
Результат = Элементы.РезультатОтчета; // Это ТабличныйДокумент на форме
Результат.Очистить();
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(Результат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
КонецПроцедуры
Проанализируем ситуацию, когда система выдает ошибку при выполнении метода КомпоновщикМакета.Выполнить(). Чаще всего это происходит из-за того, что КомпоновщикНастроек, расположенный в реквизитах формы, «привязан» к основной схеме компоновки, а вы пытаетесь использовать программно загруженную схему из макета.
Выясним причину: если в новой схеме поля или их пути отличаются от тех, что были в основной схеме, компоновщик не сможет сопоставить настройки. Чтобы этого избежать, необходимо переинициализировать настройки компоновщика под конкретную схему:
// Перед получением настроек инициализируем источник доступных настроек
ИсточникНастроек = Новый ИсточникДоступныхНастроекКомпоновкиДанных(СхемаКомпоновкиДанных);
Отчет.КомпоновщикНастроек.Инициализировать(ИсточникНастроек);
Настройки = Отчет.КомпоновщикНастроек.ПолучитьНастройки();
Рассмотрим более современный способ, который появился в последних релизах платформы. Теперь в тексте запроса СКД можно напрямую обращаться к параметру, содержащему таблицу значений. Это избавляет от необходимости создавать «Набор данных - объект».
В тексте запроса СКД мы пишем:
ВЫБРАТЬ * ИЗ &МояТЗ КАК ТЗ
Проанализируем программную установку: в этом случае нам не нужно передавать ВнешниеНаборыДанных в процессор компоновки. Мы просто устанавливаем значение параметра в компоновщике настроек:
ПараметрТЗ = Отчет.КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы.Найти("МояТЗ");
Если ПараметрТЗ <> Неопределено Тогда
ПараметрТЗ.Значение = ТаблицаДанных;
ПараметрТЗ.Использование = Истина;
КонецЕсли;
Важный нюанс: при таком подходе СКД автоматически определит поля таблицы значений. Однако структура колонок вашей ТаблицыДанных должна строго соответствовать тем полям, которые вы ожидаете получить в результате.
При программном формировании отчета из модуля формы часто «теряется» стандартная расшифровка (возможность открыть документ при клике на ячейку). Чтобы расшифровка работала, выполним следующие действия:
Выполнить компоновщика макета.Инициализировать процессора компоновки.Посмотрим на пример кода с поддержкой расшифровки:
ДанныеРасшифровки = Новый ДанныеРасшифровкиКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);
// Помещаем расшифровку во временное хранилище
АдресРасшифровки = ПоместитьВоВременноеХранилище(ДанныеРасшифровки, ЭтаФорма.УникальныйИдентификатор);
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных, ДанныеРасшифровки);
// Привязываем адрес к табличному документу на форме
Элементы.РезультатОтчета.ДанныеРасшифровки = АдресРасшифровки;
Мы разобрали два основных способа передачи данных в СКД из модуля формы. Первый способ (через набор данных - объект) является универсальным и проверенным временем. Второй (через параметры в 8.3.17+) позволяет писать более лаконичный код, но требует актуальной версии платформы. Помните, что ключевым моментом при программной работе с СКД является правильная инициализация Компоновщика настроек и передача Данных расшифровки, если вам требуется интерактивность в отчете.