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