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