Как программно передать список значений в параметры отчета СКД

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

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

Настройка схемы компоновки данных и текста запроса

Прежде чем передавать список значений из встроенного языка, необходимо убедиться, что сама схема компоновки данных готова к приему множественного значения. Разберем два обязательных требования на уровне схемы.

  1. Флаг доступности списка значений. В схеме компоновки данных перейдем на закладку Параметры. Для нужного параметра (например, Подразделение) найдем колонку Доступен список значений и установим в ней флаг. Если этого не сделать, интерфейс СКД и внутренние проверки типов будут ожидать одиночное значение заданного типа.
  2. Синтаксис условия в запросе. Одной только установки флага в параметрах схемы недостаточно. В тексте запроса набора данных условие фильтрации должно использовать операцию проверки вхождения во множество: ГДЕ Таблица.Подразделение В (&Подразделение) или ГДЕ Таблица.Подразделение В ИЕРАРХИИ (&Подразделение). Если в тексте запроса оставить оператор равенства = &Подразделение, то при передаче списка или массива система выдаст ошибку несовместимости типов на уровне СУБД.
  3. Обработка пустого списка через фигурные скобки. Если параметр может оставаться незаполненным, жесткое условие в запросе приведет к выборке пустой таблицы. Чтобы условие автоматически исключалось из результирующего SQL-запроса, если параметр не передан или выключен, поместим конструкцию в фигурные скобки СКД: {ГДЕ Таблица.Подразделение В (&Подразделение)}.

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

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


СписокПодразделений = Новый СписокЗначений;
Для Каждого стрКот Из Стр.Ссылка.ПодразделенияТаб Цикл
    // Ошибка: в список добавляется вся строка таблицы, а не ссылка
    СписокПодразделений.Добавить(стрКот);
КонецЦикла;

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

Чтобы исправить эту ошибку, необходимо обращаться напрямую к реквизиту строки, где хранится ссылка:


СписокПодразделений = Новый СписокЗначений;
Для Каждого стрКот Из Стр.Ссылка.ПодразделенияТаб Цикл
    СписокПодразделений.Добавить(стрКот.Подразделение);
КонецЦикла;

Способ 1: Прямая установка значения в коллекции параметров настроек

Рассмотрим базовый вариант установки параметра через поиск элемента в коллекции ПараметрыДанных текущих настроек схемы компоновки данных. Этот способ часто используется при явной работе со структурой схемы:


СхемаКомпоновкиДанных = Отчет.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
Настройки = СхемаКомпоновкиДанных.НастройкиПоУмолчанию;

СписокПодразделений = Новый СписокЗначений;
Для Каждого СтрТЧ Из Стр.Ссылка.ПодразделенияТаб Цикл
    СписокПодразделений.Добавить(СтрТЧ.Подразделение);
КонецЦикла;

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

Здесь важно обязательно проверять, найден ли параметр методом Найти(), и не забывать взводить свойство Использование = Истина, иначе параметр будет проигнорирован при компоновке результата.

Способ 2: Оптимальная установка через метод УстановитьЗначениеПараметра и метод ВыгрузитьКолонку

Код можно существенно упростить и сделать более надежным. Платформа 1С предоставляет встроенный метод УстановитьЗначениеПараметра для коллекции ПараметрыДанных, а также метод ВыгрузитьКолонку для табличных частей и таблиц значений.

Разберем преимущества этого подхода:

  1. Метод табличной части ВыгрузитьКолонку("ИмяРеквизита") сразу возвращает массив ссылок без необходимости писать цикл Для Каждого.
  2. Параметры СКД в запросе отлично принимают объект типа Массив наравне с объектом СписокЗначений.
  3. Метод Настройки.ПараметрыДанных.УстановитьЗначениеПараметра() самостоятельно находит параметр по имени, присваивает ему значение и выставляет флаг Использование = Истина. Если параметра не было в пользовательских настройках, метод создаст его автоматически.

Посмотрим на оптимизированный пример кода:


СхемаКомпоновкиДанных = Отчет.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
Настройки = СхемаКомпоновкиДанных.НастройкиПоУмолчанию;

// Получаем массив подразделений в одну строку
МассивПодразделений = Стр.Ссылка.ПодразделенияТаб.ВыгрузитьКолонку("Подразделение");

// Устанавливаем значение параметра без ручного поиска и флагов использования
Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("Подразделение", МассивПодразделений);

Если в схеме компоновки данных принципиально требуется именно СписокЗначений, массив легко загрузить в него пакетно с помощью метода ЗагрузитьЗначения():


СписокПодразделений = Новый СписокЗначений;
СписокПодразделений.ЗагрузитьЗначения(МассивПодразделений);
Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("Подразделение", СписокПодразделений);

Способ 3: Использование программного отбора вместо параметров

Проанализируем альтернативный архитектурный вариант. Во многих задачах вместо явного объявления параметров в запросе выгоднее использовать стандартный механизм отборов компоновки данных. Это избавляет от необходимости жестко прописывать условия в секции ГДЕ текста запроса.

Посмотрим, как настроить отбор по списку значений программно:


СхемаКомпоновкиДанных = Отчет.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
Настройки = СхемаКомпоновкиДанных.НастройкиПоУмолчанию;

МассивПодразделений = Стр.Ссылка.ПодразделенияТаб.ВыгрузитьКолонку("Подразделение");

// Добавляем элемент отбора компоновки данных
ЭлементОтбора = Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Подразделение");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке; // или ВСпискеПоИерархии
ЭлементОтбора.ПравоеЗначение = МассивПодразделений;
ЭлементОтбора.Использование = (МассивПодразделений.Количество() > 0);

Главный плюс отборов СКД заключается в том, что при отключении отбора (когда передан пустой список и Использование = Ложь) платформа самостоятельно модифицирует текст запроса к базе данных, полностью исключая лишние проверки без ручного добавления условий в фигурные скобки.

← На главную