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