Как передать параметры из формы в СКД при отключенной стандартной обработке?

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

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

Причина возникновения проблемы

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

Способ 1: Использование реквизитов объекта отчета

Это один из самых простых и надежных способов. Разберем его по шагам:

  1. Перейдем в конфигуратор и откроем метаданные нашего отчета.
  2. Добавим необходимые параметры в ветку Реквизиты (не путать с параметрами самой схемы СКД).
  3. На управляемой форме отчета убедимся, что основным реквизитом является Отчет. Разместим реквизиты объекта на форме, перетащив их из колонки Отчет (например, Отчет.ДатаНачала).
  4. Теперь в модуле объекта, внутри процедуры ПриКомпоновкеРезультата, мы можем обращаться к этим данным напрямую по именам реквизитов.

Проанализируем пример кода в модуле объекта:


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    // Обращаемся к реквизиту объекта напрямую
    ВыбраннаяОрганизация = Организация; 
    
    // Или через ЭтотОбъект для наглядности
    НужнаяДата = ЭтотОбъект.ПериодОтчета;
    
    // Далее используем эти переменные для фильтрации таблицы значений
    // или передачи в запрос
КонецПроцедуры

Способ 2: Получение значений из пользовательских настроек СКД

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

Разберем, как программно «достать» значение параметра по его имени:


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

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

Способ 3: Синхронизация данных формы и компоновщика

Иногда требуется более гибкий контроль. Вы можете оставить реквизиты на форме как «Реквизиты формы» (не привязанные к объекту), но перед вызовом формирования отчета принудительно записывать их в параметры компоновщика. Рассмотрим, как это реализовать в модуле формы:


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

Важный нюанс: при работе с управляемыми формами система часто дублирует настройки в ПользовательскиеНастройки. Поэтому самым надежным методом остается использование метода УстановитьЗначениеПараметра, если это поддерживается версией платформы, или прямой перебор элементов, как показано во втором способе.

Работа с внешними наборами данных

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

В этом случае алгоритм действий следующий:

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

Пример программного формирования с внешним набором:


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

// Формируем внешние данные (ТЗ), используя наши параметры
ТаблицаДанных = СформироватьМоюТаблицу(ПараметрИзФормы); 

ВнешниеНаборыДанных = Новый Структура;
ВнешниеНаборыДанных.Вставить("ИмяВнешнегоНабораВ_СКД", ТаблицаДанных);

ДанныеРасшифровки = Новый ДанныеРасшифровкиКомпоновкиДанных;
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;

МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);

ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных, ДанныеРасшифровки);

ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);

Подведем итоги

Для передачи параметров из формы в серверный код СКД при СтандартнаяОбработка = Ложь наиболее эффективно:

← На главную