Как настроить отбор по типу документа в динамическом списке 1С для составных типов данных

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

При разработке интерфейсов на управляемых формах 1С часто возникает задача отфильтровать элементы динамического списка по конкретному виду документа. Это особенно актуально, когда источником данных выступает регистр сведений или регистр накопления с реквизитом составного типа (например, РеестрДокументов.Ссылка или Регистратор).

В этом материале мы подробно разберем, почему возникают ошибки при попытке напрямую установить отбор по выражению ТИПЗНАЧЕНИЯ(...), и рассмотрим правильные механизмы фильтрации данных на управляемой форме.

Анализ частых ошибок при фильтрации по типу

Разберем типичные проблемы, с которыми сталкиваются разработчики при реализации такой задачи:

  1. Ошибка «Неверные параметры в операции сравнения. Нельзя сравнивать поля неограниченной длины и поля несовместимых типов». Попытка наложить элемент отбора Компоновки Данных (СКД) на поле, сформированное через ТИПЗНАЧЕНИЯ(Ссылка), передавая в качестве правого значения системный объект Тип или строку, приводит к ошибке СУБД. Язык запросов 1С не поддерживает прямое сравнение результата функции ТИПЗНАЧЕНИЯ() с текстовым представлением или переменной типа Тип.
  2. Ошибка «Невозможно применить фиксированные настройки. Пересекаются элементы отбора». Данное исключение возникает, если в коллекцию Список.Отбор.Элементы повторно добавляется условие по полю, для которого уже установлен отбор (например, сохраненный в пользовательских настройках или заданный на этапе конфигуратора).

Способ 1. Использование параметра запроса с пустой ссылкой (Рекомендуемый подход)

Наиболее надежный и правильный метод решения задачи — модификация текста запроса динамического списка и передача в качестве параметра отбора пустой ссылки нужного типа документа вместо объекта Тип.

Рассмотрим пошагово настройку данного механизма.

Шаг 1. Настройка произвольного запроса динамического списка

Перейдем в свойства динамического списка, установим флаг Произвольный запрос и добавим в секцию ГДЕ проверку с использованием конструкции ВЫБОР КОГДА:


ВЫБРАТЬ
	РеестрДокументов.Ссылка КАК Ссылка,
	РеестрДокументов.Дата КАК Дата
ИЗ
	РегистрСведений.РеестрДокументов КАК РеестрДокументов
ГДЕ
	ВЫБОР
		КОГДА &ОтборТипДокумента <> НЕОПРЕДЕЛЕНО И &ОтборТипДокумента <> ЗНАЧЕНИЕ(Документ.ПустаяСсылка)
			ТОГДА ТИПЗНАЧЕНИЯ(РеестрДокументов.Ссылка) = ТИПЗНАЧЕНИЯ(&ОтборТипДокумента)
		ИНАЧЕ ИСТИНА
	КОНЕЦ

Благодаря этой конструкции, если параметр &ОтборТипДокумента равен Неопределено, условие в секции ГДЕ всегда возвращает ИСТИНА, и список отображает все документы без ограничений.

Шаг 2. Организация поля выбора на форме

Создадим реквизит формы ВыбранныйТип с типом ОписаниеТипов. При открытии формы ограничим доступный выбор только нужными документами:


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

Шаг 3. Обработка выбора пользователя

При изменении значения в поле выбора получаем тип, находим его метаданные, создаем пустую ссылку и передаем ее в параметр динамического списка:


&НаКлиенте
Процедура ПолеВыбораТипаПриИзменении(Элемент)
	ПрименитьФильтрПоТипуНаСервере();
КонецПроцедуры

&НаСервере
Процедура ПрименитьФильтрПоТипуНаСервере()
	
	Если ЗначениеЗаполнено(ВыбранныйТип) И ВыбранныйТип.Типы().Количество() > 0 Тогда
		// Извлекаем выбранный тип из ОписанияТипов
		ТипЭлемента = ВыбранныйТип.Типы()[0];
		
		// Получаем объект метаданных по типу
		МетаданныеДокумента = Метаданные.НайтиПоТипу(ТипЭлемента);
		
		Если МетаданныеДокумента <> Неопределено Тогда
			// Формируем пустую ссылку соответствующего типа
			ПустаяСсылка = Документы[МетаданныеДокумента.Имя].ПустаяСсылка();
			Список.ПараметрыЗапроса.УстановитьЗначениеПараметра("ОтборТипДокумента", ПустаяСсылка);
		КонецЕсли;
	Иначе
		// Сбрасываем отбор
		Список.ПараметрыЗапроса.УстановитьЗначениеПараметра("ОтборТипДокумента", Неопределено);
	КонецЕсли;
	
КонецПроцедуры

Способ 2. Оптимизация производительности с помощью оператора ССЫЛКА

Проверка ТИПЗНАЧЕНИЯ(Ссылка) = ТИПЗНАЧЕНИЯ(&Параметр) заставляет СУБД вычислять функцию для каждой записи таблицы, что может замедлять работу динамического списка на больших объемах данных.

Если перечень поддерживаемых документов фиксирован, наиболее производительным решением будет использование оператора ССЫЛКА:


ВЫБРАТЬ
	Реестр.Ссылка КАК Ссылка,
	Реестр.Дата КАК Дата
ИЗ
	РегистрСведений.РеестрДокументов КАК Реестр
ГДЕ
	ВЫБОР
		КОГДА &ИмяТипа = "РеализацияТоваровУслуг" ТОГДА Реестр.Ссылка ССЫЛКА Документ.РеализацияТоваровУслуг
		КОГДА &ИмяТипа = "ПоступлениеТоваровУслуг" ТОГДА Реестр.Ссылка ССЫЛКА Документ.ПоступлениеТоваровУслуг
		ИНАЧЕ ИСТИНА
	КОНЕЦ

В этом случае в параметр запроса &ИмяТипа достаточно передавать простую строку с именем объекта метаданных (например, "РеализацияТоваровУслуг"). На уровне SQL-запроса это преобразуется в прямую проверку кода типа, что позволяет СУБД эффективно задействовать индексы таблицы.

Безопасное управление отборами через БСП

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


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

Данный подход корректно обновляет существующие элементы отбора в коллекции Список.Отбор без риска возникновения конфликтов со встроенными настройками формы.

← На главную