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

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

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

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

Разбор типовых ошибок: почему код падает в рантайме

Проанализируем распространенную ситуацию: разработчик пытается перебрать коллекцию пользовательских настроек в цикле и применить строковое сравнение имен параметров:


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

При выполнении этого кода система выдает исключение Поле объекта не обнаружено (Параметр). Выясним причину такого поведения платформы:

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

Способ 1. Корректная установка параметров в форме отчета

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


&НаКлиенте
Процедура УстановитьПараметрыПериодаВОтчете()
    
    УстановитьПараметрСКД("ДатаНачала", Объект.ДатаНачала);
    УстановитьПараметрСКД("ДатаОкончания", КонецДня(Объект.ДатаОкончания));
    
КонецПроцедуры

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

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


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

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

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

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

В этом случае отключаем стандартную обработку и вызываем метод ПолучитьНастройки() у компоновщика. Этот метод автоматически объединяет фиксированные и пользовательские настройки в единый результирующий объект:


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

Способ 3. Декларативная настройка через «СтандартныйПериод» без программного кода

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

Разберем настройку по шагам:

  1. Откроем схему компоновки данных и перейдем на вкладку Параметры.
  2. Создадим вспомогательный параметр с именем ПериодОтчета и типом данных СтандартныйПериод.
  3. Для параметра ПериодОтчета снимем флаг Ограничение доступности и включим его в пользовательские настройки на вкладке «Настройки».
  4. Для рабочих параметров запроса ДатаНачала и ДатаОкончания установим флаг Ограничение доступности (чтобы скрыть их из диалога пользователя) и заполним колонку Выражение:
    • Для ДатаНачала: &ПериодОтчета.ДатаНачала
    • Для ДатаОкончания: КонецПериода(&ПериодОтчета.ДатаОкончания, "День")

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

Способ 4. Использование типовых функций БСП

Если разработка ведется в конфигурации на базе Библиотеки Стандартных Подсистем (БСП), рекомендуется использовать готовые сервисные функции общих модулей. Это сокращает объем исходного кода и защищает от ошибок обновления структуры настроек:


// Безопасная установка параметра с автоматической обработкой пользовательских настроек
ОбщегоНазначенияКлиентСервер.УстановитьПараметрКомпоновкиДанных(
    Отчет.КомпоновщикНастроек,
    "ДатаНачала",
    Объект.ДатаНачала,
    Истина
);

ОбщегоНазначенияКлиентСервер.УстановитьПараметрКомпоновкиДанных(
    Отчет.КомпоновщикНастроек,
    "ДатаОкончания",
    КонецДня(Объект.ДатаОкончания),
    Истина
);

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

← На главную