Как правильно ограничить список выбора при автоподборе в 1С:Предприятие 8.3

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

При разработке интерфейсов на управляемых формах часто возникает задача ограничить список элементов, которые предлагаются пользователю при вводе текста в поле выбора. Например, нам нужно показывать только те товары, которые есть в наличии на конкретном складе, или только те документы, которые соответствуют определенному виду операции. Однако стандартный механизм платформы часто ведет себя «самостоятельно», добавляя в список элементы из истории выбора или результаты полнотекстового поиска, игнорируя программные фильтры.

В этой статье мы подробно разберем, почему стандартная обработка может продолжать работать, даже если вы установили СтандартнаяОбработка = Ложь, и как реализовать надежный фильтр при вводе по строке.

Разбор работы события АвтоПодбор

Событие АвтоПодбор возникает на клиенте, когда пользователь вводит символы в текстовое поле ввода. Рассмотрим типовую структуру этого обработчика:


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

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

Пример реализации фильтрации по сложным условиям

Предположим, нам нужно фильтровать контрагентов не только по наименованию, но и по ИНН, при этом исключая тех, кто помечен на удаление. Проанализируем пример кода, который эффективно решает эту задачу:


&НаСервереБезКонтекста
Функция ПолучитьСписокВыбораКонтрагента(Знач СтрокаПоиска)
    
    СписокВозврат = Новый СписокЗначений;
    
    // Очистка строки от лишних символов (опционально)
    СтрокаПоиска = СокрЛП(СтрокаПоиска); 
    
    Если СтрДлина(СтрокаПоиска) < 3 Тогда
        Возврат СписокВозврат;
    КонецЕсли;    

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

В данном примере мы используем &НаСервереБезКонтекста, что критически важно для производительности интерфейса. Контекстные вызовы при каждом нажатии клавиши могут привести к значительным задержкам (фризам) формы.

Почему в списке появляются «лишние» элементы?

Если вы реализовали код выше, но в выпадающем списке все равно видите значения, которые не соответствуют вашему запросу (они часто подсвечиваются зеленым или отображаются внизу списка), значит, работают дополнительные механизмы платформы.

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

Альтернативный метод: Динамические параметры выбора

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

Рассмотрим пример, когда при создании формы нам нужно жестко ограничить выбор только двумя конкретными организациями. Мы можем программно установить ПараметрыВыбора для элемента формы:


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

Этот метод хорош тем, что он автоматически влияет и на форму выбора (при нажатии на кнопку «Показать все»), и на ввод по строке. Платформа сама наложит фильтр ГДЕ Ссылка В (&МассивРазрешенныхСсылок) на все запросы подбора.

Рекомендация: Модуль менеджера

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

Проанализировав все способы, можно сделать вывод: для простых фильтров по реквизитам лучше использовать СвязиПараметровВыбора или ПараметрыВыбора. Если же логика требует сложных расчетов (например, запрос к регистру остатков с учетом даты документа), используйте событие АвтоПодбор совместно с отключением ИсторииВыбораПриВводе.

← На главную