gifts2017

Реализация поиска по первым символам в Управляемых формах

Опубликовал Дмитрий Рудаков (Дмитрий Рудаков) в раздел Администрирование - Поиск данных

Многим в управляемых формах не хватает поиска по подстроке, который был реализован в обычных формах. Данная публикация описывает, как можно реализовать поиск в управляемых формах, который подобен механизму "поиска по подстроке" на стандартной панели обычных форм.

                Пользователь кликают ячейку в колонку которая его интересует,  когда решил что пора искать нажимает CTRL+S, набирает первые символы искомого объекта и далее нажимает вперед или назад. Поиск работает аналогично как обычных формах.

 

Краткое описание алгоритма:

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

 

                Далее идет краткое описание пунктов на которые нужно обратить внимание когда вы будите писать аналогичный механизм на реальные управляемые формы.  Эти пункты нельзя назвать инструкцией к написанию, вашего поиска, это скорее пункты по которым можно внести четкую ясность как работает код в опубликованной конфигурации на что можно ориентироваться при написании уже ваших алгоритмов.

 

1) Создаем форму списка

2) У формы списка создаем два реквизита

а) СтрокаПоиска с типом Строка

б) ВыборкаПоОбъект с типом таблица значений

3)На форме списка размещаем реквизит формы "СтрокаПоиска" в поле ввода и назначаем горячую клавишу "Ctrl+S".

 

4) Создаем две команды формы Вперед и Назад, размещаем их на форме списка. Командам назначаем обработчики.

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

К примеру запрос

  ВЫБРАТЬ

Номенклатура.Ссылка КАК Ссылка,
Номенклатура.Родитель,
Номенклатура.ОсновнойПоставщик.Наименование КАК ОсновнойПоставщик,
Номенклатура.Наименование
ПОМЕСТИТЬ ТаблицаНоменклатуры
ИЗ
Справочник.Номенклатура КАК Номенклатура
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ТаблицаНоменклатуры.Ссылка,
ТаблицаНоменклатуры.Родитель,
ТаблицаНоменклатуры.ОсновнойПоставщик,
ТаблицаНоменклатуры.Наименование
ИЗ
ТаблицаНоменклатуры КАК ТаблицаНоменклатуры
ГДЕ
(
&актинаяЯчйка ПОДОБНО &СтрокаПоиска
ИЛИ ТаблицаНоменклатуры.Ссылка = &Ссылка)

УПОРЯДОЧИТЬ ПО
&ПараметрУПР

  

В этом запросе потом меняем

 


ЯчекааПоиска="ТаблицаНоменклатуры."+АктинаяЯчейка;
ТекстЗапроса=СхемаКомпановкиДанныхР.НаборыДанных.УпорядТаблица.Запрос;

ТекстЗапроса=СтрЗаменить(ТекстЗапроса,"&ПараметрУПР",Порядок);
ТекстЗапроса=СтрЗаменить(ТекстЗапроса,"&актинаяЯчйка",ЯчекааПоиска);

СхемаКомпановкиДанныхР.НаборыДанных.УпорядТаблица.Запрос=ТекстЗапроса;

Обращаю внимание что все колонки по которым будет осуществляться поиск, выбираем данные во временную таблицу и преобразуем их в строки для возможности дальнейшего сравнения.

 

5) программно переносим отборы настроенные в динамическом списке в нашу СКД поиска (этого пока не реализовано в примере, если будет актуально хотя бы нескольким пользователям то можно и доработать).

               

6) Так же в настройках СКД предусмотрительно добавляем возможные отборы, для иерархического справочника это будет Родитель элемента.

 

В случае если поиск в иерархическом справочнике, и отображение не списком то будет заполнять отбор

 

Если ПараметрыПоиска.Отображение<>"Список" тогда
// Натсройка отборов
НастройкиР.Отбор.Элементы[0].Использование=истина;
НастройкиР.Отбор.Элементы[0].ПравоеЗначение=ССылка.Родитель;

КонецЕсли;

 7) У элемента формы СПИСОК создаем событие "СписокПриАктивизацииЯчейки" в нем прописываем заполнение переменой "АктинаяЯчейка" объявленной в модуле формы:


&НаКлиенте
Перем АктинаяЯчейка;
&НаКлиенте
Процедура СписокПриАктивизацииЯчейки(Элемент)
АктинаяЯчейка=Элемент.ТекущийЭлемент.Имя;
КонецПроцедуры

8) У поля ввода "СтрокаПоиска" (пункт 3), создаем обработчик события "АвтоПодбор", в нем прописываем:

 &НаКлиенте

Процедура СтрокаПоискаАвтоПодбор(Элемент, Текст, ДанныеВыбора, Ожидание, СтандартнаяОбработка)

ПараметрыПоиска=ФормированиеСтруктурыПоиска();
ПоискПодобноНаСервер(ПараметрыПоиска);

КонецПроцедуры

 

9)В обработчиках команд форм "ВПЕРЕД" и "НАЗАД"  пишем

 

 &НаКлиенте

Процедура Вперед(Команда)

СтрокаДокумента=КонтрлоьПеремещения();

НомерТекущегоДокумента=СтрокаДокумента[0].СистемныеПоляНомерПоПорядку;

Если
ВыборкаПоОбъект.Количество() > НомерТекущегоДокумента Тогда
Элементы.Список.ТекущаяСтрока=ВыборкаПоОбъект[НомерТекущегоДокумента].ССылка;
Иначе
Сообщить("Элемент не найден, или поиск окончен");
КонецЕсли;

КонецПроцедуры

&НаКлиенте
Процедура Назад(Команда)

СтрокаДокумента=КонтрлоьПеремещения();

НомерТекущегоДокумента=СтрокаДокумента[0].СистемныеПоляНомерПоПорядку;

Если
НомерТекущегоДокумента-2 >=0 Тогда
Элементы.Список.ТекущаяСтрока=ВыборкаПоОбъект[НомерТекущегоДокумента-2].ССылка;
Иначе
Сообщить("Элемент не найден, или поиск окончен");
КонецЕсли;



КонецПроцедуры

10) Пишем вспомогательные процедуры

 &НаКлиенте

Функция ФормированиеСтруктурыПоиска()

ПараметрыПоиска=Новый Структура;
ПараметрыПоиска.Вставить("Порядок",Строка(ЭтаФорма.Список.Порядок));
ПараметрыПоиска.Вставить("Ссылка",Элементы.Список.ТекущаяСтрока);
ПараметрыПоиска.Вставить("АктинаяЯчейка",АктинаяЯчейка);
ПараметрыПоиска.Вставить("СтрокаПоиска",Элементы.СтрокаПоиска.ТекстРедактирования);
ПараметрыПоиска.Вставить("Отображение",Строка(Элементы.Список.Отображение));
Возврат
ПараметрыПоиска;

КонецФункции
// ()

&НаСервереБезКонтекста
Функция ПоискПодобно(ПараметрыПоиска)

Порядок=ПараметрыПоиска.Порядок;
АктинаяЯчейка=ПараметрыПоиска.АктинаяЯчейка;
ССылка=ПараметрыПоиска.ССылка;
СтрокаПоиска=ПараметрыПоиска.СтрокаПоиска+"%";

СхемаКомпановкиДанныхР=Справочники.Номенклатура.ПолучитьМакет("Поиск");
ЯчекааПоиска="ТаблицаНоменклатуры."+АктинаяЯчейка;
ТекстЗапроса=СхемаКомпановкиДанныхР.НаборыДанных.УпорядТаблица.Запрос;
ТекстЗапроса=СтрЗаменить(ТекстЗапроса,"&ПараметрУПР",Порядок);
ТекстЗапроса=СтрЗаменить(ТекстЗапроса,"&актинаяЯчйка",ЯчекааПоиска);
СхемаКомпановкиДанныхР.НаборыДанных.УпорядТаблица.Запрос=ТекстЗапроса;
КомпновщиеНастроекР=Новый КомпоновщикНастроекКомпоновкиДанных;
КомпновщиеНастроекР.ЗагрузитьНастройки(СхемаКомпановкиДанныхР.НастройкиПоУмолчанию);

НастройкиР=КомпновщиеНастроекР.Настройки;
НастройкиР.ПараметрыДанных.Элементы[0].Значение=СтрокаПоиска;
НастройкиР.ПараметрыДанных.Элементы[1].Значение=ССылка;
если
ПараметрыПоиска.Отображение<>"Список" тогда
// Натсройка отборов
НастройкиР.Отбор.Элементы[0].Использование=истина;
НастройкиР.Отбор.Элементы[0].ПравоеЗначение=ССылка.Родитель;

КонецЕсли;
КомпоновщикМакетаР=Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновкиР=КомпоновщикМакетаР.Выполнить(СхемаКомпановкиДанныхР,НастройкиР, , ,Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));

ПроцессорКомпоновкиДанныхР=Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновкиДанныхР.Инициализировать(МакетКомпоновкиР);

ПроцессорВыводВКолецкцию=Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ВыборкаПоОбъект = Новый ТаблицаЗначений;

ПроцессорВыводВКолецкцию.УстановитьОбъект(ВыборкаПоОбъект);
ПроцессорВыводВКолецкцию.Вывести(ПроцессорКомпоновкиДанныхР);


Возврат
ВыборкаПоОбъект;



КонецФункции
// ПоискПодобно()

&НаСервере
Процедура ПоискПодобноНаСервер(ПараметрыПоиска)
табл=ПоискПодобно(ПараметрыПоиска);
Если
ТипЗнч(табл)=ТИп("ТаблицаЗначений") тогда
ЗначениеВРеквизитФормы(табл,"ВыборкаПоОбъект");
ЭтаФорма.СтрокаПоиска=ПараметрыПоиска.СтрокаПоиска;
КонецЕсли;
КонецПроцедуры

Скачать файлы

Наименование Файл Версия Размер
Поиска по первым символам база + пояснения 73
.rar 393,48Kb
07.11.12
73
.rar 393,48Kb Скачать

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Сергей Сытько (8SiriuS8) 21.08.12 11:10
(0) На второй картинке ошибка в тексте
2. Сергей (seermak) 21.08.12 13:49
&НаКлиенте
Процедура ПоискАвтоПодбор(Элемент, Текст, ДанныеВыбора, Ожидание, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
ПоискАвтоПодбор_Сервер(ВРег(Текст));
КонецПроцедуры

&НаСервере
Процедура ПоискАвтоПодбор_Сервер(Знач СтрокаСравнения)
УдалитьОтборУСписокЗначений(СписокДанных.Отбор, Новый ПолеКомпоновкиДанных("Литера"));
ЗаполнитьСписокЗначений(СписокДанных.Отбор, Новый ПолеКомпоновкиДанных("СтрокаПодбора"), СтрокаСравнения, ВидСравненияКомпоновкиДанных.Содержит);
КонецПроцедуры


&НаСервере
Процедура ЗаполнитьСписокЗначений(ОтборСКД, Знач ЛевоеЗначение, Знач ПравоеЗначение, ВидСравнения = Неопределено)
ЭлементыОтбора = ОтборСКД.Элементы;
ЭлементОтбораДанных = Неопределено;
Для Каждого ЭлементОтбора Из ЭлементыОтбора Цикл
Если ЭлементОтбора.ЛевоеЗначение = ЛевоеЗначение Тогда
Если ЭлементОтбораДанных = Неопределено Тогда
ЭлементОтбораДанных = ЭлементОтбора;
Иначе
ЭлементОтбора.Использование = Ложь;
КонецЕсли;
КонецЕсли;
КонецЦикла;

Если ЭлементОтбораДанных = Неопределено Тогда
ЭлементОтбораДанных = ЭлементыОтбора.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбораДанных.ЛевоеЗначение = ЛевоеЗначение;
КонецЕсли;
ЭлементОтбораДанных.ВидСравнения = ВидСравнения;
ЭлементОтбораДанных.ПравоеЗначение = ПравоеЗначение;
ЭлементОтбораДанных.Использование = Истина;
КонецПроцедуры
&НаСервере
Процедура УдалитьОтборУСписокЗначений(ОтборСКД, ЛевоеЗначение)
ЭлементыОтбора = ОтборСКД.Элементы;
МассивОтборов = Новый Массив;
Для Каждого ЭлементОтбора Из ЭлементыОтбора Цикл
Если ЭлементОтбора.ЛевоеЗначение = ЛевоеЗначение Тогда
МассивОтборов.Добавить(ЭлементОтбора);
КонецЕсли;
КонецЦикла;

Для Каждого ЭлементОтбора Из МассивОтборов Цикл
ЭлементыОтбора.Удалить(ЭлементОтбора);
КонецЦикла;
КонецПроцедуры

на и не мучайся, вот еще в реквизитах поля поиска - обновление текста редактирования = не использовать
3. Arch_1 (Дмитрий Рудаков) 22.08.12 05:34
4. Stamper (Stamper) 22.08.12 10:50
помню, пытались мы как-то внедрить веб-расширение для 1С 8.0
так вот там автоподбор вариантов выбора просто жутко тормозило. и это понятно, т.к. нужно было прокачивать дополнительную информацию.
как я понимаю, по причинам производительности и исключили эту "фичу" из управляемого (который потенциально будет веб-) интерфейса.
как с производительностью у этого решения?
отдельная благодарность будет автору за запись видеоролика какого-нибудь.
p.s. плюсанул
5. Arch_1 (Дмитрий Рудаков) 22.08.12 10:59
(4)
1) У меня пока нет заказчиков мест тестирования этого алгоритма на реальных данных, подумаю разместить демо базу с УФ где нибудь и посмотрю как работает... однако когда время выделить и для этого пока не знаю...

2) Какой видеоролик хотите ? По написанию?

3) Думаю это все таки решение преимущественно для толстых клиентов, у меня уже есть заказчики которые хотят в одной колонке видеть разные реквизиты, а это можно реализовать только динамическим списком, и поиск хотят тоже иметь.
6. al petrov (petrov_al) 22.08.12 11:04
Автор, все гораздо проще, не изобретай велосипед...смотри продвинутый курс гилева 1с8.2 а особенно события.
7. Arch_1 (Дмитрий Рудаков) 22.08.12 11:17
(6) что конкретно, по вашему мнению, не правильно? (как-нибудь пересмотрю)
8. Stamper (Stamper) 22.08.12 11:46
(5)ролик, в котором можно было бы оценить быстродействие. чтоб было ясно, похоже на работу в толстом клиенте, или нет
9. bulpi bulpi (bulpi) 22.08.12 13:16
1)Поиск по первым символам в обычных формах работает все же не так.
2)Молодец, что хоть это сделал. Но нюхом чую, что должно быть проще.
3)Без обид : Не работай там , где нужно что-то объяснять - учитель, репетитор. Не твое это :)
10. Serg Kondrasgov (SergDi) 22.08.12 19:03
давайте вставлю свои 5 копеек по поводу поиска по подстроке...

в модуле менеджера справочника номенклатуры пишешь код в процедуре ОбработкаПолученияДанныхВыбора(), например такой код:


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

Запрос.УстановитьПараметр("Артикул",Параметры.СтрокаПоиска);

Результат = Запрос.Выполнить();
ТаблицаРезультатов = Результат.Выгрузить();
МассивТоваров = ТаблицаРезультатов.ВыгрузитьКолонку("Товар");

ДанныеВыбора = Новый СписокЗначений;
ДанныеВыбора.ЗагрузитьЗначения(МассивТоваров);


СтандартнаяОбработка = Ложь;

КонецПроцедуры
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа