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