Как передать массив или таблицу данных в параметр и отбор СКД в 1С?

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

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

Рассмотрим по шагам, как правильно реализовать заполнение параметров и отборов СКД из программного кода в модуле объекта отчета.

Особенности передачи данных в СКД

Проанализируем основные технические нюансы, о которых важно помнить при работе с параметрами и отборами СКД:

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

Способ 1. Установка значения параметра данных СКД

Разберем пример, когда в схеме компоновки данных создан параметр с именем СписокОрганизаций, а в тексте запроса СКД указано условие вида ГДЕ РеализацияТоваровУслуг.Контрагент В (&СписокОрганизаций).

Для программной подстановки подготовленного списка элементов в модуль объекта отчета добавляется процедура ПриКомпоновкеРезультата:


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    // 1. Формируем список значений или массив с нужными объектами
    СписокОрганизаций = Новый СписокЗначений;
    
    // Заполняем список контрагентами (например, дочерними организациями)
    МассивДочерних = ПолучитьДочерниеОрганизации(Справочники.Контрагенты.НайтиПоКоду("000000001"));
    СписокОрганизаций.ЗагрузитьЗначения(МассивДочерних);
    
    // 2. Находим параметр в настройках компоновщика
    ПараметрСписокОрганизаций = КомпоновщикНастроек.Настройки.ПараметрыДанных.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных("СписокОрганизаций"));
    
    Если ПараметрСписокОрганизаций <> Неопределено Тогда
        ПараметрСписокОрганизаций.Значение = СписокОрганизаций;
        ПараметрСписокОрганизаций.Использование = Истина;
    КонецЕсли;

КонецПроцедуры

Способ 2. Программное добавление и установка элемента отбора СКД

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

Посмотрим на пример установки отбора вида В Списке для поля Организатор:


// Формируем список значений для отбора
СписокОрганизаций = Новый СписокЗначений;
СписокОрганизаций.ЗагрузитьЗначения(МассивКонтрагентов);

// Ищем существующий отбор или создаем новый
ПолеОтбора = Новый ПолеКомпоновкиДанных("Организатор");
ЭлементНайден = Ложь;

Для Каждого ЭлементОтбора Из КомпоновщикНастроек.Настройки.Отбор.Элементы Цикл
    Если ЭлементОтбора.ЛевоеЗначение = ПолеОтбора Тогда
        ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке;
        ЭлементОтбора.ПравоеЗначение = СписокОрганизаций;
        ЭлементОтбора.Использование = Истина;
        ЭлементНайден = Истина;
        Прервать;
    КонецЕсли;
КонецЦикла;

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

Пример рекурсивного сбора подчиненных элементов

Рассмотрим вспомогательную функцию для рекурсивного поиска всех дочерних контрагентов компании, если требуется собрать всю структуру подчиненности:


Функция ПолучитьДочерниеОрганизации(ГоловнойКонтрагент) Экспорт
    
    Результат = Новый Массив;
    Результат.Добавить(ГоловнойКонтрагент);
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	Контрагенты.Ссылка КАК Ссылка
        |ИЗ
        |	Справочник.Контрагенты КАК Контрагенты
        |ГДЕ
        |	Контрагенты.ГоловнаяКомпания = &ГоловнаяКомпания";
    
    Запрос.УстановитьПараметр("ГоловнаяКомпания", ГоловнойКонтрагент);
    Выборка = Запрос.Выполнить().Выбрать();
    
    Пока Выборка.Следующий() Цикл
        
        ДочерниеЭлементы = ПолучитьДочерниеОрганизации(Выборка.Ссылка);
        Для Каждого Элемент Из ДочерниеЭлементы Цикл
            Если Результат.Найти(Элемент) = Неопределено Тогда
                Результат.Добавить(Элемент);
            КонецЕсли;
        КонецЦикла;
        
    КонецЦикла;
    
    Возврат Результат;

КонецФункции

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

← На главную