Как передать таблицу значений в Построитель отчета 1С

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

При работе с классическим инструментом Построитель отчета в 1С программисты часто сталкиваются с необходимостью объединить данные из информационной базы с данными, которые уже находятся в памяти в виде Таблицы Значений (ТЗ). Попытка передать таблицу значений напрямую в параметр запроса (через &ТЗ) неизменно приводит к ошибке: "Неверные параметры". Это происходит из-за особенностей внутреннего парсера Построителя, который не умеет типизировать сложные структуры данных на лету.

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

Почему Построитель отчета не принимает таблицу значений напрямую

Разберем ситуацию: ПостроительОтчета предназначен для динамического формирования текста запроса на основе настроек пользователя (отборы, группировки, поля). Когда мы присваиваем текст свойству Текст, Построитель анализирует его, чтобы понять структуру метаданных. Если в тексте встречается параметр, который должен содержать таблицу, парсер ожидает простую ссылку или примитивный тип для формирования условий отбора. Обработка временных таблиц из внешних источников требует иного подхода.

Способ №1: Использование Менеджера временных таблиц

Проанализируем самый технически совершенный метод. Если нам нужно использовать ТЗ именно внутри запроса (например, для соединения с физическими таблицами базы данных), мы можем воспользоваться механизмом Менеджера временных таблиц. Построитель отчета использует объект Запрос, которому можно назначить предварительно заполненный менеджер.

Рассмотрим по шагам, как это реализовать:

  1. Подготовим таблицу значений и обязательно типизируем её колонки. Это критически важно, так как запрос не сможет создать временную таблицу из колонок с неопределенным типом.
  2. Создадим объект Запрос и поместим в него нашу ТЗ во временную таблицу.
  3. Передадим МенеджерВременныхТаблиц этого запроса в Построитель.

Посмотрим на пример кода:


// 1. Подготовка ТЗ с типами
ТЗ_Данные = Новый ТаблицаЗначений;
ТЗ_Данные.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
ТЗ_Данные.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 3)));

// Заполнение ТЗ данными...

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

// 3. Настройка построителя
Построитель = Новый ПостроительОтчета;
Построитель.Текст = 
"ВЫБРАТЬ
|   ВТ_ВнешниеДанные.Номенклатура,
|   ВТ_ВнешниеДанные.Количество,
|   Остатки.ВНаличииОстаток
|ИЗ
|   ВТ_ВнешниеДанные КАК ВТ_ВнешниеДанные
|   ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки
|   ПО ВТ_ВнешниеДанные.Номенклатура = Остатки.Номенклатура";

// Важный момент: передаем менеджер в построитель
Построитель.Запрос.МенеджерВременныхТаблиц = МенеджерВТ;
Построитель.ЗаполнитьНастройки();
Построитель.Выполнить();

Этот метод позволяет оперировать данными ТЗ как полноценной таблицей БД, сохраняя при этом все возможности Построителя по группировке и оформлению.

Способ №2: Использование ОписанияИсточникаДанных

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

Рассмотрим, как это работает:


// Предположим, ТЗ_Итог уже содержит все данные
ОписаниеТЗ = Новый ОписаниеИсточникаДанных(ТЗ_Итог);
Построитель = Новый ПостроительОтчета;
Построитель.ИсточникДанных = ОписаниеТЗ;

// Построитель сам создаст колонки на основе состава ТЗ
Построитель.ЗаполнитьНастройки();
Построитель.Вывести(ЭлементыФормы.ПолеТабличногоДокумента);

Преимущества: Максимальная простота и отсутствие проблем с парсером запроса. Недостатки: Построитель теряет связь с базой данных. Если пользователь захочет добавить новый отбор, Построитель не сможет "пересчитать" данные из БД — он будет фильтровать только те строки, которые уже есть в переданной ТЗ.

Способ №3: Динамическая модификация текста запроса

Проанализируем ситуацию, когда нам нужно программно внедрить условия в запрос. Некоторые разработчики используют метод "подмены" текста. В тексте запроса оставляется маркер, который перед выполнением заменяется на описание полей или условий.

Например, в тексте Построителя написано:

//ГДЕ_ДОП_УСЛОВИЕ

Перед вызовом метода Выполнить() мы можем сделать следующее:


ТекстДопУсловия = "И Номенклатура В (&СписокНоменклатуры)";
Построитель.Текст = СтрЗаменить(Построитель.Текст, "//ГДЕ_ДОП_УСЛОВИЕ", ТекстДопУсловия);
Построитель.ЗаполнитьНастройки();

Однако помните: любое изменение свойства Текст после того, как пользователь уже сделал интерактивные настройки (выбрал поля или группировки), может привести к сбросу этих настроек. Поэтому данный метод следует использовать с осторожностью и только до вызова ЗаполнитьНастройки().

Сравнение Построителя отчета и СКД в контексте ТЗ

Разберем частое заблуждение о том, что Система компоновки данных (СКД) тоже не умеет работать с ТЗ. На самом деле, СКД гораздо гибче в этом вопросе. В СКД существует механизм Внешних наборов данных. Вы можете определить в схеме набор данных типа "Объект", назвать его, и при выполнении компоновки передать туда таблицу значений. Это позволяет связывать ТЗ и запросы к БД на уровне самой схемы, что в Построителе отчета реализуется гораздо сложнее (через МВТ, как мы рассмотрели выше).

Итоги и рекомендации

Выясним, какой метод выбрать:

Помните, что Построитель отчета — это объект для работы с обычными формами. В современных конфигурациях на управляемых формах рекомендуется использовать исключительно СКД, так как она предоставляет на порядок больше инструментов для манипуляции данными, включая работу с внешними источниками без необходимости сложного ручного программирования менеджеров временных таблиц.

← На главную