Потребовалось тут как то реализовать в документе ввод по строке с поиском по строковым реквизитам справочника. Реализовывать по старинке через запрос при работающем и более функциональном полнотекстовом поиске совершенно не хотелось. К сожалению, на данный момент, даже при включении в настройках справочника использования полнотекстового поиска при вводе по строке поиск происходит только по указанным полям в настройке "Поле ввода".
Для демонстрации решения в тестовой базе буду использовать процедуру ОбработкаПолученияДанныхВыбора модуля менеджера справочника, чтобы механизм поиска действовал во всей конфигурации.
Первые наброски выглядят следующим образом:
Процедура ОбработкаПолученияДанныхВыбора(ДанныеВыбора, Параметры, СтандартнаяОбработка) СтандартнаяОбработка = Ложь; СписокПоиска = ПолнотекстовыйПоиск.СоздатьСписок(Параметры.СтрокаПоиска, 50); ОбластьПоиска = Новый Массив; ОбластьПоиска.Добавить(Метаданные.Справочники.Номенклатура); СписокПоиска.ОбластьПоиска = ОбластьПоиска; СписокПоиска.ПерваяЧасть(); Если СписокПоиска.Количество() Тогда ДанныеВыбора = Новый СписокЗначений; Для Каждого ЭлементПоиска Из СписокПоиска Цикл ЗаполнитьЗначенияСвойств(ДанныеВыбора.Добавить(), ЭлементПоиска); КонецЦикла; КонецЕсли; КонецПроцедурыПроверяем работу кода. Добавляем описание товара, не забываем обновить индекс полнотекстового поиска.
Выполняем ввод по строке в документе:
Поиск отрабатывает, но представление результата не информативно. Возвращаемся в конфигуратор и смотрим, из чего состоит ЭлементПоиска.
Свойство | Значение | Тип | |
ЭлементПоиска | ЭлементСпискаПолнотекстовогоПоиска | ЭлементСпискаПолнотекстовогоПоиска | |
Значение | Стол журнальный | СправочникСсылка.Номенклатура | |
Метаданные | Список товаров | ОбъектМетаданных | |
Описание | "Описание товара: Стекло, дуб, ковка" | Строка | |
Представление | "Стол журнальный" | Строка |
Перепишем заполнение элементов списка, представление элемента списка формируем из свойств "Представление" и "Описание".
Процедура ОбработкаПолученияДанныхВыбора(ДанныеВыбора, Параметры, СтандартнаяОбработка) СтандартнаяОбработка = Ложь; СписокПоиска = ПолнотекстовыйПоиск.СоздатьСписок(Параметры.СтрокаПоиска, 50); СписокПоиска.ОбластьПоиска.Добавить(Метаданные.Справочники.Номенклатура); СписокПоиска.ПерваяЧасть(); Если СписокПоиска.Количество() Тогда ДанныеВыбора = Новый СписокЗначений; Для Каждого ЭлементПоиска Из СписокПоиска Цикл ДанныеВыбора.Добавить(ЭлементПоиска.Значение, ЭлементПоиска.Представление + "; " + ЭлементПоиска.Описание); КонецЦикла; КонецЕсли; КонецПроцедурыРезультат уже несколько лучше.
Но если посмотреть на работу стандартного механизма, то увидим, что результат поиска подсвечивается. Было бы замечательно реализовать такое отображение и нашем варианте.
Синтаксис-помощник подсказывает, что представлением элемента списка может выступать как Строка, так и ФорматированнаяСтрока. Ок, это как раз наш вариант. Осталось только выделить результат поиска в описании элемента. Используя метод ПолучитьОтображение можно получить отображение результата полнотекстового поиска в HTML и XML представлениях.
<html> <head> <style type="text/css"> html { overflow:auto; } body { margin: 10px; font-family: Arial,sans-serif; font-size: 10pt; overflow:auto; } div.main { overflow:auto; height:100%; } div.presentation { font-size: 11pt; } div.textPortion { padding-bottom: 16px; } span.bold { font-weight: bold; } a { text-decoration:none; color:#0066CC; } a:hover { text-decoration:underline; } </style> </head> <body> <div class="main"> <div class="presentation"> <a id="FullTextSearchListItem" href="#" sel_num="0">Список товаров: Стол журнальный</a> </div> <div class="textPortion"> Описание товара: <span class="bold" style="background-color:#CCFFCC">Стекло</span>, дуб, ковка </div> </div> </body> </html>
HTML-представление показалось мне неудобным для разбора, поэтому используем второй вариант. XML-представление дает на выходе объект ЧтениеXML, который в свою очередь передается в ПостроительDOM. Окончательный вариант процедуры:
Процедура ОбработкаПолученияДанныхВыбора(ДанныеВыбора, Параметры, СтандартнаяОбработка) СтандартнаяОбработка = Ложь; СписокПоиска = ПолнотекстовыйПоиск.СоздатьСписок(Параметры.СтрокаПоиска, 50); СписокПоиска.ОбластьПоиска.Добавить(Метаданные.Справочники.Номенклатура); СписокПоиска.ПерваяЧасть(); Если СписокПоиска.Количество() Тогда ОписаниеСписка = СписокПоиска.ПолучитьОтображение(ВидОтображенияПолнотекстовогоПоиска.XML); ЧтениеДОМ = Новый ПостроительDOM; ПредставлениеСписка = ЧтениеДОМ.Прочитать(ОписаниеСписка); СписокПредставлений = ПредставлениеСписка.ПолучитьЭлементыПоИмени("textPortion"); МассивПредставлений = Новый Массив; ШрифтВыделения = Новый Шрифт(,,Истина); ЦветВыделения = WebЦвета.Зеленый; Для Каждого ЭлементПредставления Из СписокПредставлений Цикл МассивФормата = Новый Массив; Для Каждого ДочернийУзел Из ЭлементПредставления.ДочерниеУзлы Цикл Если ДочернийУзел.ТипУзла = ТипУзлаDOM.Текст Тогда ШрифтСтроки = Неопределено; ЦветСтроки = Неопределено; ИначеЕсли ДочернийУзел.ТипУзла = ТипУзлаDOM.Элемент Тогда ШрифтСтроки = ШрифтВыделения; ЦветСтроки = ЦветВыделения; КонецЕсли; СтрокаФормата = Новый ФорматированнаяСтрока(ДочернийУзел.ТекстовоеСодержимое, ШрифтСтроки, ЦветСтроки); МассивФормата.Добавить(СтрокаФормата); КонецЦикла; МассивПредставлений.Добавить(МассивФормата); КонецЦикла; ДанныеВыбора = Новый СписокЗначений; НомерЭлемента = 0; Для Каждого ЭлементПоиска Из СписокПоиска Цикл НомерЭлемента = НомерЭлемента + 1; Значение = ЭлементПоиска.Значение; Если Значение.ЭтоГруппа Тогда Продолжить; КонецЕсли; ПредставлениеЭлемента = Новый ФорматированнаяСтрока(ЭлементПоиска.Представление + ", ", МассивПредставлений[НомерЭлемента - 1]); ЭлементСписка = ДанныеВыбора.Добавить(ЭлементПоиска.Значение, ПредставлениеЭлемента); КонецЦикла; КонецЕсли; КонецПроцедуры
Проверяем, результат получается вполне сносный.
Как вариант:
ОтветитьУдалить//ОбработкаПолученияДанныхВыбора - Произвольный запрос и формирование "ДанныеВыбора"
//Обход списка значений "ДанныеВыбора", Замена представления на форматированную строку
Для каждого СтрокаВыбора Из ДанныеВыбора Цикл
СтрокаВыбора.Представление = СтроковыеФункцииКлиентСервер.ВернутьФорматированнуюСтрокуПоиска(СтрокаВыбора.Представление,Параметры.СтрокаПоиска);
КонецЦикла;
Функция ВернутьФорматированнуюСтрокуПоиска(СтрокаДляРазбора,СтрокаПоиска) Экспорт
СтрокаЗамены = "";
Для стр = 1 По СтрДлина(СтрокаПоиска) Цикл
СтрокаЗамены = СтрокаЗамены + "@";
КонецЦикла;
//РазложитьСтроку - Функция БСП из "СтроковыеФункцииКлиентСервер"
МассивСтрок = РазложитьСтрокуВМассивСлов(СтрЗаменить(СтрокаДляРазбора,СтрокаПоиска,СтрокаЗамены+"_"+СтрокаЗамены),СтрокаЗамены);
//СобираемСтроку
ФормСтрока = Новый Массив;
Для каждого СтрокаИзМассива Из МассивСтрок Цикл
Если СтрокаИзМассива = "_" Тогда
ФормСтрока.Добавить(Новый ФорматированнаяСтрока(СтрокаПоиска,Новый Шрифт(,,Истина),WebЦвета.ЗеленыйЛес));
Иначе
ФормСтрока.Добавить(Новый ФорматированнаяСтрока(СтрокаИзМассива))
КонецЕсли;
КонецЦикла;
Возврат Новый ФорматированнаяСтрока(ФормСтрока);
КонецФункции
Функция чуствительна к регистру.
УдалитьМожет кому пригодится, функцию написал независимую от регистра
УдалитьФункция ВернутьФорматированнуюСтрокуПоиска(СтрокаДляРазбора, СтрокаПоиска) Экспорт
СтрокаВВерхнемРегистре = Врег(СтрокаДляРазбора);
СтрокаПоискаВВерхнемРегистре = Врег(СтрокаПоиска);
ФормСтрока = Новый Массив;
Для Стр = 1 По СтрЧислоВхождений(СтрокаВВерхнемРегистре, СтрокаПоискаВВерхнемРегистре) Цикл
Индекс = Найти(СтрокаВВерхнемРегистре, СтрокаПоискаВВерхнемРегистре);
Если НЕ Индекс = 1 Тогда
ФормСтрока.Добавить(Новый ФорматированнаяСтрока(Сред(СтрокаДляРазбора,1,Индекс-1)));
КонецЕсли;
ФормСтрока.Добавить(Новый ФорматированнаяСтрока(Сред(СтрокаДляРазбора, Индекс, СтрДлина(СтрокаПоиска)), Новый Шрифт(,,Истина),WebЦвета.ЗеленыйЛес));
СтрокаДляРазбора = Прав(СтрокаДляРазбора, СтрДлина(СтрокаДляРазбора) - (Индекс + (СтрДлина(СтрокаПоиска)-1)));
СтрокаВВерхнемРегистре = Прав(СтрокаВВерхнемРегистре, СтрДлина(СтрокаВВерхнемРегистре) - (Индекс + (СтрДлина(СтрокаПоиска)-1)));
КонецЦикла;
ФормСтрока.Добавить(Новый ФорматированнаяСтрока(СтрокаДляРазбора));
Возврат Новый ФорматированнаяСтрока(ФормСтрока);
КонецФункции