Как отфильтровать список справочника по данным регистра сведений в 1С

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

При разработке интерфейсов на управляемых формах 1С часто возникает задача: отобразить в динамическом списке справочника только те элементы, которые соответствуют определенным условиям в периодическом или непериодическом регистре сведений. Например, показать в списке ФизическиеЛица только тех людей, у которых в регистре сведений установлен признак Плательщик.

Попытки решить эту задачу «в лоб» — созданием дублирующих форм или прямой перезаписью текста запроса динамического списка через свойство Список.ТекстЗапроса — приводят к ошибкам, потере стандартной функциональности и усложнению поддержки конфигурации. Разберем архитектурно правильные способы реализации такой фильтрации.

Почему не работает прямая замена текста запроса в коде

Проанализируем частую ошибку начинающих разработчиков: вызов команды, в которой выполняется присвоение Список.ТекстЗапроса = "...". В управляемом приложении такое поведение приводит к следующим проблемам:

  1. Флаг произвольного запроса. Если у реквизита формы типа ДинамическийСписок флаг Произвольный запрос отключен (значение Список.ПроизвольныйЗапрос = Ложь), прямое присвоение текста запроса динамически игнорируется платформой либо вызывает исключение. Для программной подмены текста необходимо явно устанавливать Список.ПроизвольныйЗапрос = Истина;.
  2. Сброс привязок и оформления. При динамической смене текста запроса в режиме «1С:Предприятие» могут сброситься привязки колонок таблицы формы к полям выборки, пользовательские настройки, группировки и условное оформление.
  3. Потеря производительности. Динамический список оптимизирован под компоновку данных. Постоянная перезапись запроса заставляет платформу заново инициализировать структуру данных формы.

Рассмотрим, как правильно решить задачу штатными средствами платформы 1С:Предприятие 8.3.

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

Основной подход заключается в том, чтобы список всегда получал расширенный состав полей через ЛЕВОЕ СОЕДИНЕНИЕ, а фактическая фильтрация выполнялась через механизм отборов компоновщика настроек динамического списка. Разберем настройку по шагам.

  1. Откроем управляемую форму списка справочника в конфигураторе.
  2. В окне реквизитов формы выделим реквизит Список и в палитре свойств установим флаг Произвольный запрос.
  3. В свойстве Основная таблица обязательно укажем наш справочник (например, Справочник.ФизическиеЛица). Это критически важно для сохранения стандартных команд добавления, удаления, контекстного меню и постраничной динамической подгрузки данных.
  4. Нажмем кнопку открытия свойства Настройка списка и в конструкторе запроса свяжем справочник с регистром сведений:

ВЫБРАТЬ
	Спр.Ссылка КАК Ссылка,
	Спр.ПометкаУдаления КАК ПометкаУдаления,
	Спр.Наименование КАК Наименование,
	Спр.Код КАК Код,
	ЕСТЬNULL(Регистр.Плательщик, ЛОЖЬ) КАК Плательщик
ИЗ
	Справочник.ФизическиеЛица КАК Спр
	ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СтатусыФизЛиц КАК Регистр
		ПО Спр.Ссылка = Регистр.ФизическоеЛицо

Если регистр сведений является периодическим, вместо основной таблицы регистра необходимо соединять справочник с виртуальной таблицей СрезПоследних.

Теперь поле Плательщик доступно для настройки отборов как пользователю (через меню Все действия — Настроить список), так и разработчику программно.

Программное управление отбором по кнопке формы

Если требуется включать или отключать фильтрацию по нажатию специальной кнопки на командной панели формы, используем программную работу с коллекцией Список.Отбор.Элементы. Рассмотрим пример обработчика команды на клиенте и сервере.


&НаКлиенте
Процедура ПоказатьТолькоПлательщиков(Команда)
	// Переключаем признак фильтрации
	ТолькоПлательщики = Не ТолькоПлательщики;
	УстановитьОтборПоПлательщикуНаСервере(ТолькоПлательщики);
КонецПроцедуры

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

Если необходимо исключить возможность снятия данного отбора пользователем через стандартную форму настройки, отбор следует устанавливать в коллекцию Список.КомпоновщикНастроек.ФиксированныеНастройки.Отбор.

Способ 2. Управление фильтрацией через параметры запроса

В некоторых сценариях удобно заложить условие непосредственно в текст произвольного запроса динамического списка с использованием управляющего параметра. Разберем этот вариант.

В тексте запроса динамического списка пропишем секцию ГДЕ:


ВЫБРАТЬ
	Спр.Ссылка КАК Ссылка,
	Спр.Наименование КАК Наименование,
	ЕСТЬNULL(Регистр.Плательщик, ЛОЖЬ) КАК Плательщик
ИЗ
	Справочник.ФизическиеЛица КАК Спр
	ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СтатусыФизЛиц КАК Регистр
		ПО Спр.Ссылка = Регистр.ФизическоеЛицо
ГДЕ
	(&ТолькоПлательщики = ЛОЖЬ ИЛИ Регистр.Плательщик = ИСТИНА)

При открытии формы и по нажатию кнопки достаточно менять значение параметра списка:


&НаСервере
Процедура УстановитьПараметрСписка(Знач ФлагПлательщики)
	Список.Параметры.УстановитьЗначениеПараметра("ТолькоПлательщики", ФлагПлательщики);
КонецПроцедуры

При передаче значения Ложь условие в секции ГДЕ будет истинным для всех строк, и список отобразит все элементы справочника. При установке значения Истина отберутся только записи с установленным признаком в регистре.

Важные технические нюансы и оптимизация

Обратим внимание на критические моменты при работе со связями в динамических списках:

  1. Уникальность связей (1:1). При выполнении ЛЕВОГО СОЕДИНЕНИЯ со срезом регистра или непериодическим регистром важно следить, чтобы по условию связи на один элемент справочника приходилась строго одна запись регистра. Если соединение вернет дубли, динамический список может завершиться системной ошибкой несоответствия ключа строки или отобразит дублирующиеся строки в таблице.
  2. Обязательное указание основной таблицы. Без заполнения свойства ОсновнаяТаблица список теряет возможность быстрой порционной выборки данных, перестает работать стандартное контекстное меню и горячие клавиши добавления/пометки на удаление.
  3. Производительность виртуальных таблиц. Если регистр сведений хранит миллионы записей, соединение с виртуальной таблицей СрезПоследних без фильтра по измерениям внутри параметров таблицы может замедлить отклик интерфейса. В таких случаях следует убедиться в наличии необходимых индексов по ведущим измерениям регистра.

Использование левого соединения с регистром в сочетании с компоновщиком настроек динамического списка позволяет гибко управлять фильтрацией, сохраняя высокую скорость работы интерфейса и чистоту исходного кода конфигурации.

← На главную