Как получить значения параметров СКД, если они выведены в пользовательские настройки (шапку отчета)?

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

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

Разберем причину проблемы: Настройки vs Пользовательские настройки

Для начала проанализируем, как СКД разделяет хранение данных. В объекте КомпоновщикНастроекКомпоновкиДанных существует две принципиально разные коллекции:

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

Важный момент: если параметр включен в пользовательские настройки, его значение в основной коллекции КомпоновщикНастроек.Настройки.ПараметрыДанных перестает обновляться автоматически. Оно остается либо пустым, либо содержит значение по умолчанию. Именно поэтому попытка найти параметр по имени в этой коллекции возвращает неактуальные данные.

Решение проблемы через метод ПолучитьНастройки()

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

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


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

    // Дальнейшая логика формирования отчета...
    
КонецПроцедуры

Разбор типичной ошибки в ПриКомпоновкеРезультата

Рассмотрим ситуацию, когда отчет формируется программно с использованием внешних наборов данных (например, Таблицы Значений). Часто программисты совершают ошибку, путая объект, возвращаемый методом ПолучитьНастройки(), и текущие настройки компоновщика. Посмотрим на примере, как нельзя делать и как исправить ситуацию.

Ошибочный подход:


// ОШИБКА: Сначала получили настройки в переменную, но потом использовали КомпоновщикНастроек.Настройки
Настройки = КомпоновщикНастроек.ПолучитьНастройки();
НачалоПериода = Настройки.ПараметрыДанных.Элементы.Найти("НачалоПериода").Значение;

// ... подготовка данных ...

// КРИТИЧЕСКАЯ ОШИБКА: Передача старых настроек в компоновщик макета
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроек.Настройки, ДанныеРасшифровки);

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

Правильный подход:

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


СтандартнаяОбработка = Ложь;

// Получаем актуальные настройки из интерфейса
ПолныеНастройки = КомпоновщикНастроек.ПолучитьНастройки();

// Извлекаем значения для формирования внешнего набора данных
НачалоПериода = ПолныеНастройки.ПараметрыДанных.Элементы.Найти("НачалоПериода").Значение;
КонецПериода = ПолныеНастройки.ПараметрыДанных.Элементы.Найти("КонецПериода").Значение;

// Обработка пустых дат
Если НачалоПериода = '00010101' Тогда НачалоПериода = НачалоДня(ТекущаяДата()); КонецЕсли;

// Получаем данные (например, из запроса или ТЗ)
ТЗ_Данных = ПолучитьТаблицуПродаж(НачалоПериода, КонецПериода);
ВнешниеНаборы = Новый Структура("ТЗ", ТЗ_Данных);

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

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

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

Как найти параметр напрямую в пользовательских настройках?

Иногда требуется не «схлопывать» все настройки, а обратиться конкретно к элементу в шапке. Это сложнее, так как коллекция ПользовательскиеНастройки.Элементы не позволяет искать по имени параметра. Поиск осуществляется по уникальному идентификатору.

Рассмотрим по шагам, как это сделать:

  1. Найдем параметр в основной коллекции КомпоновщикНастроек.Настройки.ПараметрыДанных.
  2. Возьмем значение свойства ИдентификаторПользовательскойНастройки у найденного элемента.
  3. Используем этот идентификатор для поиска в коллекции КомпоновщикНастроек.ПользовательскиеНастройки.Элементы.

Пример программного поиска:


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

Полезные советы по работе с параметрами в СКД

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

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

← На главную