Как получить и изменить параметры СКД программно в 1С?

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

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

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

Почему параметры формы не попадают в запрос: основные причины

Проанализируем ключевые механизмы платформы 1С, приводящие к ошибкам при работе с параметрами:

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

Способ 1. Корректное чтение актуальных параметров, заданных пользователем

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

Рассмотрим пример функции для чтения значения параметра:


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

Если ЗначениеПараметра <> Неопределено И ЗначениеПараметра.Использование Тогда
    ДатаНачала = ЗначениеПараметра.Значение;
Иначе
    // Параметр не задан или отключен пользователем
    ДатаНачала = '00010101';
КонецЕсли;

Способ 2. Программное изменение параметра с отображением на форме

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

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

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

Посмотрим на практическую реализацию этого алгоритма:


ИмяПараметра = Новый ПараметрКомпоновкиДанных("КонецПериода");

// Поиск параметра в структуре настроек
НайденныйПараметр = Отчет.КомпоновщикНастроек.Настройки.ПараметрыДанных.НайтиЗначениеПараметра(ИмяПараметра);

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

Также можно выполнить прямой перебор элементов коллекции пользовательских настроек, если требуется универсальный поиск без привязки к идентификаторам:


ИмяПараметра = Новый ПараметрКомпоновкиДанных("КонецПериода");

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

Способ 3. Переопределение параметров в событии «ПриКомпоновкеРезультата»

Если перед выполнением отчета требуется программно скорректировать параметры (например, рассчитать начало и конец месяца или подставить границы периода по умолчанию), обработку следует выполнять в модуле объекта отчета в процедуре ПриКомпоновкеРезультата.

Рассмотрим правильный шаблон переопределения параметров:


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

Рекомендации по настройке параметров периода в схеме СКД

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

  1. На вкладке Параметры схемы компоновки данных создаем один общий параметр ПериодОтчета с типом СтандартныйПериод и включаем его в пользовательские настройки.
  2. Для служебных параметров виртуальных таблиц НачалоПериода и КонецПериода устанавливаем флаг Ограничение доступности (чтобы скрыть их из интерфейса).
  3. В поле Выражение для скрытых параметров указываем:
    • Для НачалоПериода: &ПериодОтчета.ДатаНачала
    • Для КонецПериода: КонецПериода(&ПериодОтчета.ДатаОкончания, "ДЕНЬ")
  4. В тексте запроса к виртуальным таблицам (например, регистра бухгалтерии или накопления) заключаем параметры в фигурные скобки:
    
    ИЗ
        РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты({&НачалоПериода}, {&КонецПериода}, ...)
    
    Это позволяет СКД корректно оптимизировать запрос к СУБД в тех случаях, когда границы периода не заданы или отключены пользователем.
← На главную