Быстрый умный поиск с выпадающим списком

Обработка + консольная утилита (exe). Работает с использованием FormEx.dll (Алексей Фёдоров aka АЛьФ), strmatch (Ракунов Александр aka skorp) и 1sqlite (Александр Орефков).
Выполняет быстрый нечеткий поиск по справочнику (по умолчанию — номенклатуры) с выводом наиболее похожих позиций в выпадающий список.
Работает на 1с 7.7.
Тестировалось на server 2003 в терминалах, в файловой БД.
Предполагаемые достоинства: пример (более) «адекватного» (по меркам автора на данный момент) поведения поисковой строки (реализовано при помощи консольной утилиты, работающей через winapi – исходники прилагаются (писалось в lazarus)) и удобной навигации по списку, во время ввода.
Является, скорее, примером для реализаций собственных адаптированных поисковых решений.

Не так давно, общаясь с пользователем, услышал жалобу на то, что новые сотрудники компании совершенно не ориентируются в номенклатуре предприятия (ТиС), что при работе с клиентами «в голос» и справочнике в 10 тыс. позиций – достаточно критично. Да и мне самому частенько приходилось «играть» с поисковой строкой, дабы обнаружить позицию, с которой «что-то не то».

Упоминание библиотеки нечеткого поиска было еще свежо в памяти (strmatch.dll от Александра Ракунова (skorp)) – потому и решил ее опробовать.
Хотелось, чтобы наиболее похожие позиции отображались во время набора (здесь, вероятно, виноват openconf+телепат+intellisence).
Для быстроты заполнения КЭШа strmatch (внутренне хранилище строк с быстрым последовательным доступом) было решено использовать 1sqlite (Александр Орефков), т.к. он уже использовался в системе, а для отслеживания начала/окончания изменения поисковой строки – Formex (Алексей Фёдоров aka АЛьФ), по той же причине.
Нужно сказать, что организовать подобный поиск можно и иными средствами, например: можно не использовать прямые запросы и обойтись strmatch + Formex (либо 1cpp) / не использовать strmatch, а просто искать по вхождениям, используя 1cpp + sqlite/vfpoledb/MSSQL и т.д.

Что делает обработка: при открытии обработки и изменении флага учета неактуальных позиций происходит заполнение/перезаполнение КЭШа strmatch. В качестве хэшей используются id справочника. При начале/продолжении ввода печатных символов с клавиатуры, либо удалении обработка начинает считать паузы между нажатиями на клавиши. При длительности паузы более определенного лимита (н-р 500 мс) запускается консольная утилитка (GetTextFrom1cedit 0.0.1 (Jill)), перехватывающая, через win api содержимое указанного окна и возвращающая текст в текстовый файл. Далее происходит сравнение строк и заполнение/перезаполнение списка похожих строк. Фокус со строки ввода, при этом, не уходит. Для навигации по списку и выбора значения используется перехват нажатий на клавиши (U93;/U95;/enter), при помощи FormEx.

Описание параметров GetTextFrom1cedit:
1 – дескриптор окна (handle) в десятиричном виде (либо «0» — если не известен)
2 – заголовок искомого окна (игнорируется, при наличии хэндла)
3 – номер 1cedit’а
4 – полный путь к текстовому файлу (файл будет создан/перезаписан)

Что делает утилита: при наличии хэндла окна находит дочернее окно класса 1cedit тем, или иным способом, в зависимости от способа вызова обработки (в модальном и не модальном режимах структура дерева дочерних окон 1с различна) и получает текст поля. При отсутствии хэндла (указан 0) ищет окно по наименованию, далее действует аналогичным образом.

Внимание: при поиске по наименованию и множестве одновременно открытых обработок (в т.ч. в нескольких 1с) с одинаковым заголовком возможны ошибки.

Зачем нужно было сочинять какие-то утилитки, если можно просто обойтись активацией поля при ложном закрытии и использовании WScript.Shell + sendkey, или просто, тем же Formex, перехватывать символы: как уже было сказано поведение поля ввода поисковой строки кажется более адекватным. Например: в модальном режиме конструкция с ложным закрытием работать откажется, а при перехвате символов довольно проблемно реализовать незамудренный (если хорошенько постараться, конечно, можно разродиться каким-нибудь монстриком, но решение с win api показалось мне более простым и менее времязатратным) алгоритм, обрабатывающий выделение части строки и ввод поверх и т.п. ситуации.

Подключение:
В «ПриНачалеРаботыСистемы»:

Попытка
ЗагрузитьВнешнююКомпоненту("1sqlite.dll");
Исключение
Предупреждение("Ошибка! Загрузить внешнюю компоненту ""1sqlite.dll"" не удалось! Обратитесь к специалисту.");
КонецПопытки;

Попытка
ЗагрузитьВнешнююКомпоненту("FormEx.dll");
Исключение
Предупреждение("Ошибка! Загрузить внешнюю компоненту ""FormEx.dll"" не удалось! Обратитесь к специалисту.");
КонецПопытки;

Попытка
ЗагрузитьВнешнююКомпоненту("StrMatch.dll");
Исключение
Предупреждение("Ошибка! Загрузить внешнюю компоненту ""StrMatch.dll"" не удалось! Обратитесь к специалисту.");
КонецПопытки; 

Кнопка вызова: 

ОткрытьФормуМодально("Отчет", Контекст, КаталогИБ()+"EXTFORMSQuicktFuzzySearchFastSearch.ert").

P.S. не рекомендуется использовать базу, в строке пути к которой, имеются кириллические символы и пробелы.

12 Comments

  1. OneS
    Не так давно, общаясь с пользователем, услышал жалобу на то, что новые сотрудники компании совершенно не ориентируются в номенклатуре предприятия (ТиС), что при работе с клиентами «в голос» и справочнике в 10 тыс. позиций – достаточно критично. Да и мне самому частенько приходилось «играть» с поисковой строкой, дабы обнаружить позицию, с которой «что-то не то».

    Это припарка. Потом придётся делать поиск в результатах поиска. Нужно убивать источник проблемы.

    Reply
  2. AnryMc

    А при чём здесь:

    рыба

    ?

    Reply
  3. Jill

    (2) AnryMc, «Является, скорее, примером для реализаций собственных адаптированных поисковых решений.»

    Хотя, конечно, можно пользовать и как готовое решение.

    Reply
  4. Jill

    (1) OneS, динамический выпадающий список, показывающий наиболее похожие позиции в порядке убывания, ИМХО, очень похож на «поиск в результатах поиска«.

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

    Ну и как уже было сказано: это, скорее, пример возможных решений. Можно глянуть и «сбахать» свою адаптацию.

    Reply
  5. OneS

    (4) когда выпадет за сотню строк, тогда может быть и дойдёт, что нужно заняться справочником.

    Reply
  6. Jill

    (5) OneS, какой ассортимент держать/закупать решают другие люди.

    Как структурировать справочник и то, как должна выглядеть строка наименования (шаблонность н-р «объем/вес_наименование_брэнд») — тоже.

    Для оптовых компаний 2-5 тыс. активных позиций — норма.

    Ну и, наконец, если глянуть в код, то 100 строк (без правки) не выпадет никогда.

    Reply
  7. AnryMc

    (3) Всё равно не понял…

    Reply
  8. Jill

    (7) AnryMc, выкинул рыбу.

    Reply
  9. Jill

    (9) margo_m09, спасибо. 🙂

    Reply
  10. lelusha

    Очень интересная идея, спасибо разработчику.

    Reply
  11. CheBurator
    «Например: в модальном режиме конструкция с ложным закрытием работать откажется,»

    — хм, не знаю, не знаю… Активно пользуюсь этим и именнов модальных формах (обработки для ТСД) — все нормально всегда было с ложным закрытием. Может, я чего-то не понял…

    Reply
  12. Jill

    (12) CheBurator, давно дело было, сейчас вряд ли вспомню — может быть чего-то напарил.

    Но точно помню что при модально запуске подбора ложное закрытие то ли в принципе вело себя некорректно, то ли что-то неладное творилось с фокусировкой.

    Reply

Leave a Comment

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