Как программно задать параметр СКД в виде списка значений и избежать типичных ошибок?

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

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

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

Выясняем причину ошибки: почему возникает «Значение не является значением объектного типа»?

Рассмотрим ситуацию, с которой часто сталкиваются начинающие разработчики. При попытке инициализировать параметр типа «Список значений» при открытии формы отчета пишется следующий код:


Склады = Новый СписокЗначений;
Склады.Добавить(Справочники.Склады.НайтиПоКоду("000000005"));
Склады.Добавить(Справочники.Склады.НайтиПоКоду("000000006"));

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

При выполнении этого кода система выдает ошибку о несоответствии типов при обращении к свойству Значение. Давайте проанализируем ситуацию.

Ошибка кроется в поведении метода Найти() коллекции параметров компоновки данных. Если в схеме компоновки данных (или в текущих настройках компоновщика) отсутствует параметр с указанным именем (в нашем примере это "Склад"), то метод Найти() не вызывает исключение сразу. Вместо этого он молча возвращает пустое значение Неопределено.

Следовательно, когда платформа пытается выполнить следующую операцию:

Неопределено.Значение = Склады;

происходит аварийное завершение работы процедуры с сообщением о том, что Неопределено не является объектом и у него нет свойства Значение. Причиной этой ошибки практически всегда является обычная опечатка в имени параметра. Например, в самой схеме СКД параметр может называться во множественном числе — "Склады", в то время как в коде программист пытается найти его в единственном числе — "Склад".

Способ 1. Программный поиск параметра и ручная установка значения

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


Склады = Новый СписокЗначений;
Склады.Добавить(Справочники.Склады.НайтиПоКоду("000000005"));
Склады.Добавить(Справочники.Склады.НайтиПоКоду("000000006"));

// Ищем параметр с точным соответствием имени в СКД
ПараметрСКД = КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы.Найти("Склады");

Если ПараметрСКД <> Неопределено Тогда
    ПараметрСКД.Значение = Склады;
    ПараметрСКД.Использование = Истина;
Иначе
    ВызватьИсключение "Параметр 'Склады' не найден в настройках компоновщика данных!";
КонецЕсли;

Обратите внимание на крайне важную строку: ПараметрСКД.Использование = Истина;. Если вы устанавливаете значение параметра вручную через коллекцию элементов, платформа требует явного указания флага использования. Если этого не сделать, свойство Использование может остаться в состоянии Ложь, и система компоновки проигнорирует заполненный вами список при формировании отчета.

Способ 2. Использование метода «УстановитьЗначениеПараметра» (Рекомендуемый)

Платформа «1С:Предприятие 8» предоставляет гораздо более удобный и безопасный метод для установки параметров — УстановитьЗначениеПараметра(). Этот метод выполняет сразу две важные функции:

  1. Быстро находит нужный параметр по его имени (или объекту ПараметрКомпоновкиДанных).
  2. Автоматически взводит флаг использования параметра в значение Истина.

Посмотрим на пример его использования:


Склады = Новый СписокЗначений;
Склады.Добавить(Справочники.Склады.НайтиПоКоду("000000005"));
Склады.Добавить(Справочники.Склады.НайтиПоКоду("000000006"));

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

Этот способ является наиболее лаконичным, читаемым и безопасным при работе на уровне основных настроек компоновщика.

Настройка самой схемы СКД: свойство «Доступен список значений»

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

  1. Откройте схему компоновки данных вашего отчета.
  2. Перейдите на вкладку Параметры.
  3. Найдите нужный параметр (например, Склады).
  4. В строке этого параметра найдите колонку Доступен список значений и установите там флаг (галочку).

Если эта галочка снята, то при попытке передать в параметр объект типа СписокЗначений система выдаст ошибку несоответствия типов при компиляции или исполнении запроса, так как СКД будет ожидать одиночную ссылку.

Главная ловушка управляемых форм: Настройки vs Пользовательские настройки

При переходе на управляемый интерфейс многие разработчики сталкиваются с тем, что код установки параметров, написанный для обычных форм, перестает работать. Вы прописываете установку параметров в процедуре ПриОткрытии на сервере, код отрабатывает без ошибок, но на форме отчета параметры остаются пустыми, а отчет формируется без учета переданных значений. В чем же дело?

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

Если для параметра в СКД включено свойство «Включать в пользовательские настройки», его реальное значение на форме берется именно из пользовательских настроек. Изменение параметров в основной коллекции настроек в этом случае просто игнорируется системой.

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


// 1. Формируем список значений
СписокСкладов = Новый СписокЗначений;
СписокСкладов.Добавить(Справочники.Склады.НайтиПоКоду("000000005"));

ИмяПараметра = "Склады";

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

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

Используя этот универсальный подход, вы гарантируете, что параметры будут корректно применены и визуально отобразятся в полях ввода на управляемой форме отчета. Для организации удобного интерфейса редактирования таких параметров подойдёт решение для стыковки элементов управляемой формы и пользовательских настроек СКД.

Особенности передачи данных: СписокЗначений или Массив?

Часто исходные данные для заполнения параметра разработчик получает из других источников — например, выгружая результат запроса. Запрос возвращает колонку значений в виде массива через метод ВыгрузитьКолонку("Ссылка"). Возникает соблазн передать этот массив напрямую в параметр СКД:


// ОШИБОЧНЫЙ ПОДХОД
МассивСкладов = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Склад");
КомпоновщикНастроек.Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("Склады", МассивСкладов);

Делать так категорически нельзя. Механизм компоновки данных строго типизирован: если для параметра включен режим «Доступен список значений», СКД ожидает объект типа СписокЗначений. Передача массива приведет к ошибке выполнения запроса внутри компоновщика. Для похожей задачи передачи табличных данных в компоновку данных можно использовать обработку-пример для установки отбора СКД по табличной части или таблице значений.

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


// ПРАВИЛЬНЫЙ ПОДХОД
МассивСкладов = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Склад");

СписокСкладов = Новый СписокЗначений;
СписокСкладов.ЗагрузитьЗначения(МассивСкладов);

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

Где правильнее инициализировать параметры?

Выбор места инициализации параметров зависит от архитектурных особенностей вашего решения и логики поведения отчета.

Вариант А. В модуле формы отчета (событие ПриОткрытии или при загрузке настроек)

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


&НаСервере
Процедура ПриЗагрузкеПользовательскихНастроекНаСервере(Настройки, ИспользуютсяСтандартныеНастройки)
    
    // Код инициализации списков значений параметров
    СписокСкладов = Новый СписокЗначений;
    СписокСкладов.Добавить(Справочники.Склады.НайтиПоКоду("000000005"));
    
    // Установка параметров СКД
    КомпоновщикНастроек.Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("Склады", СписокСкладов);
    
КонецПроцедуры

Вариант Б. В модуле объекта отчета (событие ПриКомпоновкеРезультата)

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

Рассмотрим пример реализации такого подхода в модуле объекта:


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

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

← На главную