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