Быстрый подбор по вхождению слова в наименование

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

И чего не сделаешь ради клиента!

Говоришь: «Нельзя этого! Не предусмотрели разрабы 1С!»

А он: «Хоцца!»

И ведь не приемлют отказа… А может, это только тогда, когда со мной работают? Умеют же другие говорить «нет», и им охотно верят! Помнится, какой-то новый клиент на полном серьезе уверял меня, что нельзя в отчет 1С вывести одновременно сумму из шапки и из табличной части одного документа по строкам, чтобы сумма в шапке не умножилась на количество строк. Так программист сказал… И сделал поэтому дублирующий табличную часть и шапку регистр, чтобы данные в отчеты выводить. Разумеется, взял за свою работу оплату…

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

З=Новый Запрос(

"ВЫБРАТЬ

| Контрагенты.Наименование КАК Наименование

|ИЗ

| Справочник.Контрагенты КАК Контрагенты

|ГДЕ

| Контрагенты.Наименование ПОДОБНО &Наименование

| И НЕ Контрагенты.ПометкаУдаления

| И НЕ Контрагенты.ЭтоГруппа

|

|УПОРЯДОЧИТЬ ПО

| Наименование");

З.УстановитьПараметр("Наименование","%"+Текст+"%");

Рез=З.Выполнить().Выгрузить();

СписокКА.ЗагрузитьЗначения(Рез.ВыгрузитьКолонку("Наименование"));

Осталось решить вопрос, как присоединенный к полю ввода список открыть. Казалось бы, простая функция: изменить программно видимость существующего списка, привязанного к элементу формы. А нету!

Но решение вроде как дает метод «ВыбратьИзСписка». Он позволяет открыть сформированный список и что-то из него выбрать. Правда, список в этом случае уже не будет списком поля ввода, а должен быть создан программно. Но разве это проблема? 

...

СписокКА = Новый СписокЗначений;

СписокКА.ЗагрузитьЗначения(Рез.ВыгрузитьКолонку("Наименование"));

ВыбратьИзСписка(СписокКА, ЭлементыФормы.ПолеКА);

Проблема появляется, когда мы это решим опробовать в работе: открывающийся список подло перехватывает фокус ввода и ждет, чтобы мы что-нибудь из него выбрали. А если мы хотим продолжить ввод слова, как тогда?

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

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

И так,  решение:

  • — Делаем список на форме, видимость = false
  • — Заполнение вешаем на обработчик автоподбора текста
  • — Заполнили — делаем видимым

И — фишка! Привязываем к форме обработчик ожидания: если список выбора открыт и фокус на поле ввода или этом списке — все ок. Как только фокус ушел на что-то еще — список закрываем.

Работает! Можно скачать в прилагаемом архиве и использовать.

21 Comments

  1. andru_dv

    А если список справочника содержит десятки тысяч наименований, какая будет производительность у этого решения?

    И ещё. Можно ли сделать распознавание регистра верхний/нижний.

    Reply
  2. serega3333

    З.УстановитьПараметр(«Наименование»,»%»+Текст+»%») — если искать товары с % и другими спецсимволами — не прокатит, будь мужиком, прокачай до конца =)

    Reply
  3. the1

    (1)ВЫБРАТЬ ПЕРВЫЕ 100 подойдет?

    Reply
  4. O-Planet

    (2) За наименования со спецсимволами нужно отрывать мышку…

    Reply
  5. TMV

    (3) the1, в ЗУП при подборе сотрудников стандартом идет 50, (1) еще можно начинать искать только после набора 3 букв и более..

    (4) интересно можно ли подобную феньку прикрутить к табличной части?

    И еще, мне ж все-таки иногда нужно из списка выбрать значение, а не просто его видеть..

    Reply
  6. O-Planet

    У меня там тоже есть параметр, после скольки символов в слове начинать искать. А по поводу ТЧ, если очень захотеть, то можно.

    Reply
  7. TMV

    (6) предлагаете двигать по форме список?

    Reply
  8. petrov_al

    А полнотекстовый поиск не пробовали, потестите…думаю по скорости он опередит ваш механизм

    Reply
  9. maxis33

    1Совцы об этом тоже подумали…

    http://v8.1c.ru/o7/201302ss/

    Reply
  10. ADirks

    (12) Круто! И всего то каких-то шесть — семь лет понадобилось 🙂

    Интересно, сколько лет понадобится, чтобы к этому ещё произвольные фильтры прикрутить?

    По хорошему, надо выделить поставщика данных для такого поля ввода, и дать им рулить как хочешь. Фильтруй по чём и как хочешь, показывай что хочешь (например, остатки товара полезно показывать). Хорошо бы ещё иконками в списке рулить, и строки раскрашивать. Но этого конечно 1С никогда не сделает.

    А в семёрке это реализовано 🙂

    Reply
  11. tango

    (12) maxis33, подумали: …а-а-а! — не нам обновлять!..

    Reply
  12. tango

    чё-та не пойму, обещалово не работает

    http://v8.1c.ru/o7/201304rl/index.htm

    платформа 8.3.2.172 — ни областей, ни ссылок

    Reply
  13. Alexander.Shvets

    Спасибо! Натолкнуло на мысль =)))

    Буду пробовать в упр. приложении реализовать… А вот это будет очень интересно =))

    Reply
  14. oslokot

    O-Planet Добрый день! можно у Вас попросить обработку.

    Сам автоподбор у меня работает, все хорошо, но не могу победить перехват фокуса.

    Идея с дополнительным списком на форме понравилась, но застрял с ее реализацией. Как то корявенько получается.

    Можно поглядеть? если не трудно, скиньте на oslokot(собака)mail.ru

    Reply
  15. kenza

    (12) maxis33, чет не могу найти у себя подобных свойств.

    Reply
  16. oslokot

    а у тебя их нет, это 8.3

    Reply
  17. stepman3

    а в тонком клиенте будет работать? 😉

    Reply
  18. hibico

    Столкнулся с подобной проблемой. Решил несколько по другому. Поле списка создается программно.

    Перем мПолеПодбора, мЭлементПодбора;
    
    Процедура ВыборВПоле(Элемент, ЭлементСписка)
    мЭлементПодбора.Значение = ЭлементСписка.Значение;
    ЭлементыФормы.Удалить(Элемент);
    КонецПроцедуры
    
    Процедура ПолеВводаАвтоПодборТекста(Элемент, Текст, ТекстАвтоПодбора, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    СписокВыбора = ЭлементыФормы.Найти(«ПолеПодбора»);
    Если СписокВыбора = Неопределено Тогда
    СписокВыбора = ЭлементыФормы.Добавить(Тип(«ПолеСписка»),»ПолеПодбора»);
    СписокВыбора.Верх = Элемент.Верх+Элемент.Высота;
    СписокВыбора.Лево = Элемент.Лево;
    СписокВыбора.Ширина = Элемент.Ширина;
    СписокВыбора.УстановитьДействие(«Выбор»,Новый Действие(«ВыборВПоле»));
    СписокВыбора.ПорядокОбхода = Элемент.ПорядокОбхода+1;
    КонецЕсли;
    
    мЭлементПодбора = Элемент;
    мПолеПодбора = СписокВыбора;
    
    СписокОтбора = ОтобратьЗначения(Текст); // отдельная процедура подбора по первым символам
    // здесь не привожу
    Если СписокОтбора.Количество()<2 Тогда
    ЭлементыФормы.Удалить(СписокВыбора);
    мПолеПодбора = Неопределено;
    Иначе
    СписокВыбора.Значение = СписокОтбора;
    СписокВыбора.Высота = 20*СписокОтбора.Количество();
    КонецЕсли;
    
    Если СписокОтбора.Количество()=1 Тогда
    ТекстАвтоПодбора = СписокОтбора[0].Значение;
    КонецЕсли;
    
    КонецПроцедуры
    
    Процедура ОбновлениеОтображения()
    Если мПолеПодбора <> Неопределено И ТекущийЭлемент <> мПолеПодбора И ТекущийЭлемент <> мЭлементПодбора Тогда
    ЭлементыФормы.Удалить(мПолеПодбора);
    КонецЕсли;
    КонецПроцедуры
    
    

    Показать

    Пример прикрепил.

    Reply
  19. luic

    Класс!!! Жаль что у меня 8.1 Очень нужная вещь!!!

    Reply
  20. adapter

    зачем изобретать велосипеды? В 8.2 все работает через процедуру

    ОкончаниеВводаТекста(Элемент, Текст, Значение, СтандартнаяОбработка)

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

    Значение = ОтобратьЗначения(Текст);

    Reply
  21. sokir

    (21) hibico, это нормально работает с полем ввода, но не работает с табличным полем, а ведь именно в табличном поле пользователи и набирают товар.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *