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