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