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