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

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

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

Зачем формировать СКД программно из модуля формы?

Стандартный механизм СКД предполагает работу с запросами к базе данных. Однако бывают ситуации, когда:

  1. Данные получены из внешних источников (API, файлы, Excel).
  2. Требуется сложная предварительная обработка данных на сервере, которую невозможно или крайне затруднительно описать одним запросом.
  3. Необходимо вывести результат в произвольный ТабличныйДокумент на форме, не используя стандартную кнопку «Сформировать» основного отчета.

Способ 1: Использование «Набора данных - объект» (внешний набор)

Это классический и самый гибкий способ. Мы создаем в макете СКД набор данных типа Объект и связываем его с нашей Таблицей Значений. Разберем этот процесс по шагам.

Шаг 1. Подготовка макета СКД. В схеме компоновки данных создадим «Набор данных - объект». В поле «Имя объекта содержащего данные» укажем идентификатор, например, "ВнешниеДанныеТЗ". Важно: необходимо вручную добавить все поля, которые есть в вашей таблице значений, строго соблюдая типы данных и имена колонок.

Шаг 2. Программный код на сервере. Рассмотрим пример формирования отчета в процедуре модуля формы:


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

Решение проблемы «Поле не найдено» при программном выводе

Проанализируем ситуацию, когда система выдает ошибку при выполнении метода КомпоновщикМакета.Выполнить(). Чаще всего это происходит из-за того, что КомпоновщикНастроек, расположенный в реквизитах формы, «привязан» к основной схеме компоновки, а вы пытаетесь использовать программно загруженную схему из макета.

Выясним причину: если в новой схеме поля или их пути отличаются от тех, что были в основной схеме, компоновщик не сможет сопоставить настройки. Чтобы этого избежать, необходимо переинициализировать настройки компоновщика под конкретную схему:


// Перед получением настроек инициализируем источник доступных настроек
ИсточникНастроек = Новый ИсточникДоступныхНастроекКомпоновкиДанных(СхемаКомпоновкиДанных);
Отчет.КомпоновщикНастроек.Инициализировать(ИсточникНастроек);
Настройки = Отчет.КомпоновщикНастроек.ПолучитьНастройки();

Способ 2: Передача Таблицы Значений через параметры запроса (Платформа 8.3.17+)

Рассмотрим более современный способ, который появился в последних релизах платформы. Теперь в тексте запроса СКД можно напрямую обращаться к параметру, содержащему таблицу значений. Это избавляет от необходимости создавать «Набор данных - объект».

В тексте запроса СКД мы пишем:

ВЫБРАТЬ * ИЗ &МояТЗ КАК ТЗ

Проанализируем программную установку: в этом случае нам не нужно передавать ВнешниеНаборыДанных в процессор компоновки. Мы просто устанавливаем значение параметра в компоновщике настроек:


ПараметрТЗ = Отчет.КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы.Найти("МояТЗ");
Если ПараметрТЗ <> Неопределено Тогда
    ПараметрТЗ.Значение = ТаблицаДанных;
    ПараметрТЗ.Использование = Истина;
КонецЕсли;

Важный нюанс: при таком подходе СКД автоматически определит поля таблицы значений. Однако структура колонок вашей ТаблицыДанных должна строго соответствовать тем полям, которые вы ожидаете получить в результате.

Особенности работы с расшифровкой

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

  1. Создадим на форме переменную (или используем реквизит) для хранения данных расшифровки.
  2. Передадим этот идентификатор в метод Выполнить компоновщика макета.
  3. Передадим его же в Инициализировать процессора компоновки.
  4. Свяжем табличный документ на форме с этими данными.

Посмотрим на пример кода с поддержкой расшифровки:


ДанныеРасшифровки = Новый ДанныеРасшифровкиКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);

// Помещаем расшифровку во временное хранилище
АдресРасшифровки = ПоместитьВоВременноеХранилище(ДанныеРасшифровки, ЭтаФорма.УникальныйИдентификатор);

ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных, ДанныеРасшифровки);

// Привязываем адрес к табличному документу на форме
Элементы.РезультатОтчета.ДанныеРасшифровки = АдресРасшифровки;

Подведем итоги

Мы разобрали два основных способа передачи данных в СКД из модуля формы. Первый способ (через набор данных - объект) является универсальным и проверенным временем. Второй (через параметры в 8.3.17+) позволяет писать более лаконичный код, но требует актуальной версии платформы. Помните, что ключевым моментом при программной работе с СКД является правильная инициализация Компоновщика настроек и передача Данных расшифровки, если вам требуется интерактивность в отчете.

← На главную