Как передать таблицу значений или временную таблицу в схему компоновки данных (СКД)?

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

При разработке отчетов на базе системы компоновки данных (СКД) разработчики нередко пытаются использовать конструкцию вида ВЫБРАТЬ ... ПОМЕСТИТЬ ВремТаб ИЗ &ТаблицаЗначений прямо в тексте набора данных типа Запрос. Разберем, почему данный синтаксис вызывает ошибку, и рассмотрим рабочие способы передачи предварительно подготовленных табличных данных в отчет СКД.

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

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

Попытка поместить в запрос схему вида ИЗ &ИмяТаблицы приведет к синтаксической ошибке при проверке запроса или при формировании настроек компоновки. Чтобы решить эту задачу, в платформе предусмотрено несколько штатных механизмов.

Способ 1. Использование объекта МенеджерВременныхТаблиц

Рассмотрим первый способ, который позволяет работать с временной таблицей в запросе СКД привычным образом. Если нам требуется полноценно соединять внешние или предварительно обработанные данные с таблицами информационной базы внутри одного запроса СУБД, оптимально использовать МенеджерВременныхТаблиц.

Разберем реализацию по шагам:

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

Посмотрим на пример программной компоновки результата в модуле отчета:


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

В тексте запроса схемы компоновки данных теперь можно свободно обращаться к ВТ_Периоды:


ВЫБРАТЬ
    ВТ.Месяц КАК Месяц,
    ВТ.Год КАК Год,
    ПродажиОбороты.СуммаОборот КАК СуммаОборот
ИЗ
    ВТ_Периоды КАК ВТ
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.Продажи.Обороты КАК ПродажиОбороты
        ПО ВТ.Месяц = ПродажиОбороты.ПериодМесяц

Важный момент: Чтобы конструктор схемы компоновки данных корректно понимал структуру полей еще до выполнения кода, в запросе СКД поля временной таблицы рекомендуется явно типизировать с помощью функций ВЫРАЗИТЬ() или ЕСТЬNULL().

Способ 2. Использование Набора данных — Объект

Проанализируем второй вариант — передачу подготовленной таблицы значений через Набор данных — Объект. Это штатный механизм СКД для передачи внешних коллекций данных без выполнения дополнительных промежуточных запросов.

Разберем порядок настройки:

  1. В схеме компоновки данных создаем новый набор данных с типом Набор данных — объект и указываем имя объекта, например, ТаблицаМесяцГод.
  2. Вручную добавляем список полей набора данных (Месяц, Год) и указываем их типы.
  3. Если требуются данные из базы, создаем второй набор данных типа Запрос и настраиваем соединение на вкладке Связи наборов данных.
  4. В модуле отчета передаем структуру с внешней таблицей в процедуру компоновки.

Посмотрим на пример программной инициализации набора данных объекта:


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    // Формируем внешние наборы данных в виде структуры
    ВнешниеНаборы = Новый Структура;
    ВнешниеНаборы.Вставить("ТаблицаМесяцГод", ТаблицаМесяцГод);
    
    Настройки = КомпоновщикНастроек.ПолучитьНастройки();
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(
        СхемаКомпоновкиДанных, 
        Настройки, 
        ДанныеРасшифровки
    );
    
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    // Передаем структуру внешних наборов вторым параметром
    ПроцессорКомпоновки.Инициализировать(
        МакетКомпоновки, 
        ВнешниеНаборы, 
        ДанныеРасшифровки
    );
    
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
    ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);
    
КонецПроцедуры

Особенность способа: Соединение набора данных типа Объект с другими наборами выполняется на уровне СКД в оперативной памяти после раздельного получения данных, а не средствами СУБД в одном запросе.

Способ 3. Перенос вычислений в СКД без промежуточных таблиц

Нередко разработчики формируют таблицу значений в коде только для того, чтобы выполнить простое преобразование дат или строковых значений (например, выделить месяц и год из даты документа). В большинстве таких случаев выгрузка в код модуля избыточна.

Посмотрим, какими встроенными инструментами СКД можно заменить промежуточную таблицу:

  1. Язык выражений СКД: На вкладках Поля и Вычисляемые поля доступны функции работы с датами — Год(), Месяц(), НачалоПериода(), КонецПериода(), Формат().
  2. Функции общих модулей: В вычисляемых полях СКД можно вызывать экспортные функции неглобальных серверных общих модулей, если требуется сложный нестандартный алгоритм обработки значений.
  3. Конструкция ВЫБОР КОГДА в запросе: Логику распределения или классификации данных можно описать непосредственно в тексте основного запроса СКД.
← На главную