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