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