Как сделать отбор в форме списка обычного приложения по наименованию ссылочного реквизита?

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

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

Ограничения стандартного отбора в объекте СправочникСписок

Проанализируем частую ошибку: разработчик пытается применить строковый вид сравнения ВидСравнения.Содержит непосредственно к ссылочному реквизиту списка:


ЭлементыФормы.СправочникСписок.Значение.Отбор.Контрагент.ВидСравнения = ВидСравнения.Содержит;
ЭлементыФормы.СправочникСписок.Значение.Отбор.Контрагент.Значение = Текст;
ЭлементыФормы.СправочникСписок.Значение.Отбор.Контрагент.Использование = Истина;

Такой подход приведет к ошибке, поскольку:

  1. Несовместимость типов: вид сравнения ВидСравнения.Содержит предназначен исключительно для строковых полей, тогда как реквизит Контрагент имеет тип СправочникСсылка.Контрагенты.
  2. Отсутствие разыменования через точку: объект СправочникСписок в обычных формах отображает данные основной таблицы без возможности динамического обращения к полям связанных таблиц (конструкции вида Отбор.Контрагент.Наименование платформой обычных форм не поддерживаются).

Способ 1. Двухэтапный отбор через запрос и список значений (основное решение)

Рассмотрим наиболее универсальное решение для обычных форм. Суть метода заключается в том, чтобы сначала запросом найти все ссылки контрагентов, наименование которых содержит введенный текст, а затем установить отбор по реквизиту Контрагент с видом сравнения ВидСравнения.ВСписке.

Разберем по шагам реализацию этого механизма:

  1. Создаем на форме текстовое поле ввода (например, с именем ПолеВводаПоискПоКонтрагенту) и кнопку поиска либо обрабатываем событие ПриИзменении поля ввода.
  2. Выполняем запрос к справочнику контрагентов с условием ПОДОБНО.
  3. Выгружаем найденные ссылки в СписокЗначений.
  4. Устанавливаем отбор в элементе управления формы.

Посмотрим на пример процедуры установки такого отбора:


Процедура УстановитьОтборПоНаименованиюКонтрагента(ИскомыйТекст)

    ОтборКонтрагент = ЭлементыФормы.СправочникСписок.Значение.Отбор.Контрагент;

    Если ПустаяСтрока(ИскомыйТекст) Тогда
        // Сбрасываем отбор, если строка поиска пуста
        ОтборКонтрагент.Использование = Ложь;
        Возврат;
    КонецЕсли;

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

    // Устанавливаем отбор по списку найденных ссылок
    ОтборКонтрагент.ВидСравнения = ВидСравнения.ВСписке;
    ОтборКонтрагент.Значение = СписокСсылок;
    ОтборКонтрагент.Использование = Истина;

КонецПроцедуры

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

Способ 2. Денормализация данных (для высоконагруженных списков)

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

  1. В справочник добавляют реквизит КонтрагентНаименование со строковым типом данных.
  2. В модуле объекта в событии ПередЗаписью организуют автоматическое заполнение этого поля строкой Контрагент.Наименование.
  3. В форме списка отбор накладывается напрямую на строковый реквизит с видом сравнения ВидСравнения.Содержит.

Способ 3. Переход на динамический список (при переводе на управляемые формы)

Если конфигурация переводится на управляемые формы, задача решается штатно средствами платформы:

  1. В свойствах динамического списка включается флаг Произвольный запрос.
  2. В тексте запроса получается поле Контрагент.Наименование.
  3. Для поля настраивается свойство ИспользоватьВсегда (если оно не выведено в видимые колонки).
  4. Отбор по наименованию устанавливается стандартным механизмом платформы через коллекцию ЭлементыОтбора динамического списка.
← На главную