Каталог решений - Расширенный автоподбор при вводе по строке в поле ввода в управляемых формах

Расширенный автоподбор при вводе по строке в поле ввода в управляемых формах

Расширенный автоподбор при вводе по строке в поле ввода в управляемых формах

В наличии

Началось все с того, что штатный автоподбор при вводе по строке в поле ввода для некоторых больших справочников устраивать перестал. Вообще, для способа поиска строки «Любая часть» он работает на первый взгляд очень хорошо: работает как полнотекстовый (т.е. по нескольким словам) даже без активации полнотекстового поиска, красиво подсвечивает слова поиска в результатах. Казалось бы, все отлично.
Но есть неприятное ограничение — всего лишь 10 значений в результирующем списке (у вас может быть несколько больше, так как платформа неявно добавляет результаты поиска по истории ввода). Для небольших справочников или справочников с разнородным ассортиментом все хорошо. Но не в моей ситуации. А простых путей увеличить количество выдаваемых строк на момент написания статьи мне обнаружить не удалось. Пришлось полностью переопределять автоподбор. Ниже речь пойдет именно об этом. И, к слову, в типовых конфигурациях для некоторых справочников используются похожие приемы для увеличения количества строк результата автоподбора.

Категория:

Описание

Ниже будет выложен готовый код. А тут несколько вводных слов к нему.

Альтернативный алгоритм максимально близок к штатному автоподбору при вводе по строке с режимом поиска по строке "Любая часть". Строки результата в которых слова поиска находятся в начале строки выдаются первыми. Чтобы изменить количество строк выдаваемого результата достаточно изменить значение переменной "МаксимумСтрокРезультата". Из забавного: подсветку слов поиска в результате пришлось реализовывать вручную в функции ПодсветитьСлова() и это оказалось сопоставимо по объему с остальным кодом.

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

Но так как может оказаться нежелательным менять алгоритм автоподбора при вводе по строке сразу для всех полей ввода в конфигурации, ниже будет демонстрация приема переопределения для конкретного поля ввода "Номенклатура" в модуле некоей формы с помощью перехвата события поля ввода "Автоподбор":

&НаКлиенте
Процедура ТоварыНоменклатураАвтоПодбор(Элемент, Текст, ДанныеВыбора, ПараметрыПолученияДанных, Ожидание, СтандартнаяОбработка)
	
	СтандартнаяОбработка = Ложь;
	ДанныеВыбора = ПолучитьДанныеВыбораРасширенные(Текст);
	
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьДанныеВыбораРасширенные(СтрокаПоиска)
	
	Возврат Справочники.Номенклатура.ПолучитьДанныеВыбора(Новый Структура("СтрокаПоиска, ВводПоСтрокеРасширенный", СтрокаПоиска, Истина));
	
КонецФункции

Как видно из кода выше, для получения данных выбора мы передаем структуру с двумя параметрами — "СтрокаПоиска" и "ВводПоСтрокеРасширенный". Первый параметр является предопределенным и обязательным. А второй — это наш опциональный признак использования альтернативного алгоритма.

Ниже код модуля менеджера справочника "Номенклатура":

Процедура ОбработкаПолученияДанныхВыбора(ДанныеВыбора, Параметры, СтандартнаяОбработка)
	
	СтрокаПоиска = СтрЗаменить(Параметры.СтрокаПоиска, """", ""); // нормализация
	
	Если СтрокаПоиска <> "" И Параметры.Свойство("ВводПоСтрокеРасширенный") Тогда
		
		МаксимумСтрокРезультата = 30;
		
		МассивСловПоиска = СтрРазделить(СтрокаПоиска, " ", Ложь);
		КоличествоСловПоиска = МассивСловПоиска.Количество();
		
		Если КоличествоСловПоиска > 0 Тогда
		
			СтандартнаяОбработка = Ложь;		
			СписокВыбора = Новый СписокЗначений;
			
			Запрос = Новый Запрос;
			
			УсловияПоиска = ""; 
			ПриоритетСортировки = "";
			Для НомерСловаПоиска = 1 По КоличествоСловПоиска Цикл
				
				СловоПоиска = МассивСловПоиска[НомерСловаПоиска - 1];
				ДлинаСловаПоиска = СтрДлина(СловоПоиска);
				
				Запрос.УстановитьПараметр("СловоПоиска" + НомерСловаПоиска, "%" + СловоПоиска + "%");
				УсловияПоиска = УсловияПоиска + "
				|	И Номенклатура.Наименование ПОДОБНО &СловоПоиска" + НомерСловаПоиска;
				
				ПриоритетСортировки = ПриоритетСортировки + СтрШаблон("
				|		КОГДА ПОДСТРОКА(Номенклатура.Наименование, 1, %1) = ""%2""
				|		  ТОГДА %3", Формат(ДлинаСловаПоиска, "ЧГ="), СловоПоиска, НомерСловаПоиска);
				
			КонецЦикла;
			
			Запрос.Текст = 
			"ВЫБРАТЬ ПЕРВЫЕ " + МаксимумСтрокРезультата + "
			|	Номенклатура.Ссылка КАК Ссылка,
			|	Номенклатура.Наименование КАК Наименование,
			|	Номенклатура.ПометкаУдаления КАК ПометкаУдаления,
			|	ВЫБОР" + ПриоритетСортировки + "
			|		ИНАЧЕ 9
			|	КОНЕЦ КАК ПриоритетСортировки
			|ИЗ
			|	Справочник.Номенклатура КАК Номенклатура
			|ГДЕ
			|	ИСТИНА" + УсловияПоиска + "
			|УПОРЯДОЧИТЬ ПО
			|	ПриоритетСортировки, Наименование";
			
			Выборка = Запрос.Выполнить().Выбрать();
			Пока Выборка.Следующий() Цикл
				
				СписокВыбора.Добавить(Новый Структура("Значение, ПометкаУдаления", Выборка.Ссылка, Выборка.ПометкаУдаления), ПодсветитьСлова(Выборка.Наименование, МассивСловПоиска));
				
			КонецЦикла;
			
			ДанныеВыбора = СписокВыбора;
			
		КонецЕсли;
		
	КонецЕсли;
	
КонецПроцедуры

Функция ПодсветитьСлова(ИсходнаяСтрока, МассивСловПодсветки, Знач ШрифтПодсветки = Неопределено, Знач ЦветПодсветки = Неопределено)
	
	МассивРезультирующихСтрок = Новый Массив;
	
	Если ШрифтПодсветки = Неопределено Тогда
		ШрифтПодсветки = Новый Шрифт(,, Истина); // жирный
	КонецЕсли;
	
	Если ЦветПодсветки = Неопределено Тогда
		ЦветПодсветки = Новый Цвет(0, 153, 0); // светло-зеленый из стандартной подсветки ввода по строке
	КонецЕсли;
	
	ИсходнаяСтрокаНормализованная = НРег(ИсходнаяСтрока); // нормализация
	ДлинаИсходнойСтроки = СтрДлина(ИсходнаяСтрокаНормализованная);
	
	// получим список диапазонов символов для подсветки
	СписокДиапазонов = Новый СписокЗначений;
	Для НомерСлова = 1 По МассивСловПодсветки.Количество() Цикл
		СловоПодсветки = НРег(МассивСловПодсветки[НомерСлова - 1]); // нормализация
		ПозицияНачалаСлова = 1;
		ДлинаСлова = СтрДлина(СловоПодсветки);
		Пока ПозицияНачалаСлова <> 0 И ПозицияНачалаСлова <= ДлинаИсходнойСтроки Цикл
			ПозицияНачалаСлова = СтрНайти(ИсходнаяСтрокаНормализованная, СловоПодсветки, , ПозицияНачалаСлова);
			Если ПозицияНачалаСлова > 0 Тогда
				МассивДиапазона = Новый Массив;
				МассивДиапазона.Добавить(ПозицияНачалаСлова);
				МассивДиапазона.Добавить(ПозицияНачалаСлова + ДлинаСлова - 1);
				СписокДиапазонов.Добавить(МассивДиапазона, Формат(ПозицияНачалаСлова, "ЧЦ=3; ЧВН="));
				ПозицияНачалаСлова = ПозицияНачалаСлова + ДлинаСлова;
			КонецЕсли;
		КонецЦикла;
	КонецЦикла;
	
	// отсортируем список диапазонов по возрастанию начал диапазонов
	СписокДиапазонов.СортироватьПоПредставлению();
	
	// сформируем массив результирующих строк с разным оформлением (подсветкой)
	СтартоваяПозиция = 1;
	Для Каждого ЭлементДиапазона Из СписокДиапазонов Цикл
		НачалоДиапазона = ЭлементДиапазона.Значение[0];
		КонецДиапазона = ЭлементДиапазона.Значение[1];
		Если НачалоДиапазона > СтартоваяПозиция Тогда // часть строки без подсветки
			ЧастьБезВыделения = Сред(ИсходнаяСтрока, СтартоваяПозиция, НачалоДиапазона - СтартоваяПозиция);
			МассивРезультирующихСтрок.Добавить(Новый ФорматированнаяСтрока(ЧастьБезВыделения));
			СтартоваяПозиция = НачалоДиапазона;
		КонецЕсли;
		Если КонецДиапазона >= СтартоваяПозиция Тогда // часть строки с подсветкой
			ЧастьВыделяемая = Сред(ИсходнаяСтрока, СтартоваяПозиция, КонецДиапазона - СтартоваяПозиция + 1);
			МассивРезультирующихСтрок.Добавить(Новый ФорматированнаяСтрока(ЧастьВыделяемая, ШрифтПодсветки, ЦветПодсветки));
			СтартоваяПозиция = КонецДиапазона + 1;
		КонецЕсли;
	КонецЦикла;
	
	Если СтартоваяПозиция <= ДлинаИсходнойСтроки Тогда // "хвост" без выделения
		Хвост = Сред(ИсходнаяСтрока, СтартоваяПозиция, ДлинаИсходнойСтроки - СтартоваяПозиция + 1);
		МассивРезультирующихСтрок.Добавить(Новый ФорматированнаяСтрока(Хвост));
	КонецЕсли;
	
	Возврат Новый ФорматированнаяСтрока(МассивРезультирующихСтрок);
	
КонецФункции

Вот, собственно, и все чем я хотел поделиться в этой статье. Надеюсь, кому-то она сэкономит время.

has been added to your cart:
Оформление заказа