Как правильно передать параметры в запрос при использовании внешнего набора данных в СКД?

Программист Управленческий учет IT и автоматизация бизнеса
← На главную

Работа с Системой Компоновки Данных (СКД) через программное формирование — одна из наиболее гибких и в то же время сложных задач для разработчика 1С. Часто возникают ситуации, когда отчет, построенный на внешнем наборе данных (например, на ТаблицеЗначений), возвращает пустой результат, хотя в консоли запросов всё работает корректно. Разберем по шагам, как избежать типичных ошибок при передаче параметров и формировании макета компоновки.

Анализ исходной проблемы: почему запрос возвращает пустоту?

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


Запрос.Текст = "ВЫБРАТЬ ... ИЗ РегистрНакопления.бит_ОборотыПоБюджетам КАК бит_ОборотыПоБюджетам
                ГДЕ бит_ОборотыПоБюджетам.Сценарий = &Сценарий
                И бит_ОборотыПоБюджетам.СтатьяОборотов.ТипСтатьи = &ТипСтатьи";

// Ошибка здесь: перепутаны типы данных
Запрос.УстановитьПараметр("Сценарий", Перечисления.бит_ТипыСтатейОборотов.БДДС); 
Запрос.УстановитьПараметр("ТипСтатьи", Справочники.СценарииПланирования.НайтиПоКоду("000000001"));

В данном примере мы видим классическую ошибку невнимательности: параметру Сценарий (который ожидает ссылку на справочник сценариев) присваивается значение из перечисления типов статей. И наоборот, параметру ТипСтатьи присваивается ссылка из справочника сценариев. 1С не выдает ошибку выполнения, так как типы формально являются ссылочными, но запрос предсказуемо возвращает пустой результат, так как ни одна запись в базе не удовлетворяет такому условию.

Правильная типизация параметров и отладка

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

Рассмотрим более надежный вариант установки параметров:


СценарийОбъект = Справочники.СценарииПланирования.НайтиПоКоду("000000001");
Если СценарийОбъект.Пустая() Тогда
    Сообщить("Внимание: Сценарий не найден!");
КонецЕсли;

Запрос.УстановитьПараметр("Сценарий", СценарийОбъект);
Запрос.УстановитьПараметр("РасходДоход", Перечисления.бит_РасходДоход.Поступление);

Нюансы работы с внешними наборами данных в СКД

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

  1. Строгое соответствие имен колонок: Имя колонки в ТаблицеЗначений должно символ в символ совпадать с «Именем поля» в схеме компоновки данных. Если в запросе вы написали Сумма КАК СуммаРегл, то в СКД поле должно называться СуммаРегл.
  2. Явная типизация колонок ТЗ: Если создать таблицу значений просто через ТЗ = Запрос.Выполнить().Выгрузить(), колонки получат типы из запроса. Однако, если вы создаете ТЗ вручную, обязательно используйте ОписаниеТипов. В противном случае СКД может некорректно обрабатывать итоги или группировки по «пустым» типам.

Пример правильного создания колонок для внешнего набора:


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

Передача управления параметрами пользователю

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

Разберем, как это сделать правильно в процедуре ПриКомпоновкеРезультата:


// Получаем настройки пользователя
Настройки = КомпоновщикНастроек.ПолучитьНастройки();

// Ищем параметр "Сценарий" в настройках СКД
ПараметрСценарий = Настройки.ПараметрыДанных.Элементы.Найти("Сценарий");
Если ПараметрСценарий <> Неопределено И ПараметрСценарий.Использование Тогда
    Запрос.УстановитьПараметр("Сценарий", ПараметрСценарий.Значение);
КонецЕсли;

Особенности инициализации процессора компоновки

При использовании СтандартнаяОбработка = Ложь мы берем на себя ответственность за весь цикл вывода. Посмотрим на последовательность действий, которую нельзя нарушать:

  1. Создание макета компоновки: Здесь мы объединяем схему и настройки (включая пользовательские).
  2. Инициализация процессора компоновки: Именно на этом этапе мы передаем структуру ВнешниеНаборыДанных.
  3. Вывод результата: Использование ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент.

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

Производительность и память

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

Итоги

Мы выяснили, что причина «пустого запроса» чаще всего кроется в несоответствии типов параметров или их значений. Для успешного построения отчета через объект СКД необходимо:

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

← На главную