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