Универсальная функция отбора в справочниках

Опубликовал Алексей Плутенко (Noy) в раздел Программирование - Инструментарий

Программисту на заметку:
Отбор элементов справочника по строковым реквизитам через прямой запрос. Универсально, для SQL и DBF. Работает очень быстро!

Для 7.7

Это скорее маленькая статья, чем обработка, но в статьях не нашел как прикреплять файл - поэтому размещаю в обработках.

 

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

 

 


 

//Функция возвращает первые (все) элементы справочника, найденные по подстроке, в списоке значений

//Справочник = Идетинтификатор справочника (строка)

//ПолеПоиска = Реквизиты, по которым делать поиск (строка, разделенная запятыми)

//Метод = Метод поиска (1-поиск по вхождению, 2-поиск по первым символам, 3-поиск по последним символам)

//Искомая строка = Что ищем (строка)

//КвоЭлементов = кол-во, указывающий сколько элементов возвращать (10 - вернуть первые 10 элементов, удовлетворяющий условию, 0 - вернуть все элементы)

Функция глФильтрСправочника(Справочник,ПолеПоиска="",Метод=1,Знач ИскомаяСтрока="", КвоЭлементов=0,спРезультатов="") Экспорт

Если ТипЗначенияСтр(спРезультатов)<>"СписокЗначений" тогда спРезультатов=СоздатьОбъект("СписокЗначений");КонецЕсли;

Если ПустоеЗначение(ПолеПоиска)+ПустоеЗначение(ИскомаяСтрока)<>0 Тогда Возврат спРезультатов; КонецЕсли;

   спПолейПоиска=СоздатьОбъект("СписокЗначений");

   спПолейПоиска.ИзСтрокиСРазделителями(""""+СтрЗаменить(ПолеПоиска,",",""",""")+"""");

для х=1 по спПолейПоиска.РазмерСписка() Цикл

Если Врег(спПолейПоиска.ПолучитьЗначение(х))=Врег("Наименование") Тогда

спПолейПоиска.УстановитьЗначение(х,"спр.DESCR");

ИначеЕсли Врег(ПолеПоиска)=Врег("Код") Тогда

спПолейПоиска.УстановитьЗначение(х,"спр.Code");

Иначе

спПолейПоиска.УстановитьЗначение(х,"$Справочник."+Справочник+"."+спПолейПоиска.ПолучитьЗначение(х));

КонецЕсли;

КонецЦикла;

   МИК=СоздатьОбъект("MetaInfoClasses");

Если МИК.ЭтоSQL_Версия()=1 тогда

НоЛок=" (NOLOCK)";

Запрос = СоздатьОбъект("ODBCRecordset");

   Иначе

Если МонопольныйРежим()=1 Тогда

Возврат спРезультатов;

КонецЕсли;

НоЛок="";

База = СоздатьОбъект("OLEDBData");

Соединение ="

|Provider=VFPOLEDB.1;

|Data Source=" + КаталогИБ() + ";

|Mode=Read;

|";

Рез = База.Соединение(Соединение);

Запрос = База.СоздатьКоманду();

КонецЕсли;

   ИскомаяСтрока=Врег(СокрЛП(ИскомаяСтрока));

   ТекстЗапроса = "

|SELECT"+?(КвоЭлементов=0,""," Top "+КвоЭлементов)+"

| спр.ID as [Элемент $Справочник."+Справочник+"]

|FROM

| $Справочник."+Справочник+" as спр"+НоЛок+"

|Where

|"+?(Метаданные.Справочник(Справочник).КоличествоУровней>1,"спр.ISFOLDER=2 AND","");

для х=1 по спПолейПоиска.РазмерСписка() Цикл

ТекПоле=спПолейПоиска.ПолучитьЗначение(х);

Если Метод=1 Тогда

ТекстЗапроса=ТекстЗапроса+"

|UPPER("+ТекПоле+") Like &apos;%&apos; + :Стр + &apos;%&apos;";

ИначеЕсли Метод=2 Тогда

ТекстЗапроса=ТекстЗапроса+"

|UPPER(Left(LTRIM("+ТекПоле+"),"+СтрДлина(ИскомаяСтрока)+"))=:Стр";

ИначеЕсли Метод=3 Тогда

ТекстЗапроса=ТекстЗапроса+"

|UPPER(RIGHT(RTRIM("+ТекПоле+"),"+СтрДлина(ИскомаяСтрока)+"))=:Стр";

КонецЕсли;

Если х<спПолейПоиска.РазмерСписка() тогда ТекстЗапроса=ТекстЗапроса+" OR"; КонецЕсли;

КонецЦикла;

ТекстЗапроса=ТекстЗапроса+"

|ORDER BY "+спПолейПоиска.ПолучитьЗначение(1);

   Запрос.УстановитьТекстовыйПараметр("Стр", ИскомаяСтрока);

Если МИК.ЭтоSQL_Версия()=1 тогда

Запрос.ВыполнитьИнструкцию(ТекстЗапроса,спРезультатов);

   Иначе

ТЗ=Запрос.ВыполнитьИнструкцию(ТекстЗапроса);

ТЗ.Выгрузить(спРезультатов,,,"Элемент");

КонецЕсли;

Возврат спРезультатов;

КонецФункции

 

 

 

 


 

 

 

Требует 1С++ (http://www.1cpp.ru/index.php/Download) - обязательно.

И Microsoft OLE DB Provider для DBF баз (http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=e1a87d8f-2d58-491f-a0fa-95a3289c5fd4).

Как внедрить:

скачать 1С++, компоненту положить в каталог ИБ (или программы)

В процедуре ПриНачалеРаботыСистемы прописать

Попытка

        ЗагрузитьВнешнююКомпоненту(КаталогИБ()+"1CPP.dll");

Исключение
        Сообщить("Ошибка при загрузке ВК 1CPP.dll");
КонецПопытки;

 

 

Добавить в глобальный модуль указанную выше функцию.

А дальше можно использовать так:

Простейший пример: На форме списка справочника товаров/клиентов добавлем поле ввода "ФильтрСтр" - тип строка и две кнопки - "Фильтр()" и "ОтменаФильтра()"

В модуль формы добавлем процедуры:

Процедура Фильтр()

ИерархическийСписок(0);

ИспользоватьСписокЭлементов(глФильтрСправочника(Вид(),"Наименование,ПолнНаименование",1,ФильтрСтр));

Форма.Обновить();

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

Процедура ОтменаФильтра()

ИспользоватьСписокЭлементов();

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

 

Это простейший вариант использования данной функции.

Есть еще вариант - в отчеты по продажам/остаткам и тп - добавляем такое же поле ввода, а в запрос добавлем условие

что-то типа: Условие (Товар в спСтрФильтр)

где спСтрФильтр=глФильтрСправочника("Номенклатура","Наименование,ПолнНаименование",1,ФильтрСтр)

в итоге будем иметь возможность строить отчеты по всем товарам, где содержится например слово "шампунь"...

 

А если еще прикрутить формекс - то можно отлавливать нажатия клавиш прямо в форме списка справочника и фильтровать на лету.

Например у себя использую такой код в форме списка (Внимание, код не универсален - "причесывайте" под себя):

Перем ПоискПоШтрихКоду, ВернутьИерархию, РежимПодбора;

Процедура ПриНажатииКнопкиКлавиатуры(КодКлавиши,Alt,Shift,Ctrl,Символ,ФСО)
    Если (Shift=1) и (Alt+Ctrl=0) и (КодКлавиши=90) Тогда
        РежимПодбора=1;
        ФСО=0;
        Возврат;
    КонецЕсли;
    Если РежимПодбора=1 Тогда
        Если КодКлавиши=90 Тогда
            ФСО=0;
            Возврат;
        КонецЕсли;
        Если (КодКлавиши<58) и (КодКлавиши>47) тогда
            ФСО=0;
            ПоискПоШтрихКоду=ПоискПоШтрихКоду+Симв(КодКлавиши);
            Если ИерархическийСписок()=1 тогда
                ВернутьИерархию=1;
                ИерархическийСписок(0);
            КонецЕсли;
            ИспользоватьСписокЭлементов(глФильтрСправочника("ТМЦ","ШтрихКод,КодЯщика",3,ПоискПоШтрихКоду,50)); Форма.Обновить();
        ИначеЕсли (КодКлавиши<106) и (КодКлавиши>95) тогда
            ФСО=0;
            Если ИерархическийСписок()=1 тогда
                ВернутьИерархию=1;
                ИерархическийСписок(0);
            КонецЕсли;
            ПоискПоШтрихКоду=ПоискПоШтрихКоду+Симв(КодКлавиши-48);
            ИспользоватьСписокЭлементов(глФильтрСправочника("ТМЦ","ШтрихКод,КодЯщика",3,ПоискПоШтрихКоду,100)); Форма.Обновить();
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Процедура ПриОтжатииКнопкиКлавиатуры(КодКлавиши,Alt,Shift,Ctrl,Символ,ФСО)
    Если (КодКлавиши=90) и (РежимПодбора=1) Тогда
        РежимПодбора=0;
        ТекЭлемент=ТекущийЭлемент();
        ПоискПоШтрихКоду="";
        ИспользоватьСписокЭлементов();
        Если ВернутьИерархию=1 тогда ИерархическийСписок(1); КонецЕсли;
        АктивизироватьОбъект(ТекЭлемент);
    КонецЕсли;   
КонецПроцедуры

В моем случае пользователь Нажимает Shift - затем клавишу "Я" и при зажатой клавишу "Я" набирает последние цифры штрихкода  - справочник мгновенно фильтруется. При отжатии клавиши "Я" фильтр сбрасывается, а курсор активизируется на элемент, который был активен при фильтре - мои юзеры просто в восторге... :)

 

В качестве демонстрации прикладываю обработку, демонстрирующую работу функции.

 

Статья расчитана в первую очередь на тех, кто хочет быстро попробовать - что же это за зверь - "прямой запрос".

 

 

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

Наименование Файл Версия Размер
Отбор по справочнику
.1243244290 40,00Kb
24.12.14
323
.1243244290 40,00Kb 323 Скачать

См. также

Добавить вознаграждение
Комментарии
1. Алексей Плутенко (Noy) 1053 25.05.09 14:03 Сейчас в теме
P.S. В базах DBF будет работать только в разделенном режиме.
2. Ёпрст Биомать, а? Верните бесплатный доступ к файлам! (Ёпрст) 1010 25.05.09 15:00 Сейчас в теме
(1) при помощи правки dbeng32 от hogik работает в любом...
3. Ёпрст Биомать, а? Верните бесплатный доступ к файлам! (Ёпрст) 1010 25.05.09 15:02 Сейчас в теме
+2 всё это конечно хорошо, но вот решение, имхо , получшее:
http://www.1cpp.ru/forum/YaBB.pl?num=1211491690
4. Алексей Плутенко (Noy) 1053 25.05.09 15:07 Сейчас в теме
(3) Не получшее, а лучше просто в разы!
Ясень пень, что моя маленькая заготовка с ней не сравниться, но как обучающий материал пойдет.
5. Ёпрст Биомать, а? Верните бесплатный доступ к файлам! (Ёпрст) 1010 25.05.09 15:14 Сейчас в теме
(4) ну ясно...и это , к (2) тоже приглядись, если что на будующее...

6. Ёпрст Биомать, а? Верните бесплатный доступ к файлам! (Ёпрст) 1010 25.05.09 15:14 Сейчас в теме
7. Алексей Плутенко (Noy) 1053 25.05.09 15:20 Сейчас в теме
8. rasswet (rasswet) 80 27.05.09 08:54 Сейчас в теме
плюсанул за идею, сам видимо пользоваться не буду
9. Anics (anics) 27.05.09 10:21 Сейчас в теме
Что с этим делать?

МИК=СоздатьОбъект("MetaInfoClasses");
{C:\DOCUMENTS AND SETTINGS\АДМИНИСТРАТОР\РАБОЧИЙ СТОЛ\FN_FINDSPR.ERT(23)}: Неудачная попытка создания объекта (MetaInfoClasses)
10. Ёпрст Биомать, а? Верните бесплатный доступ к файлам! (Ёпрст) 1010 27.05.09 10:25 Сейчас в теме
(9) загрузить ВК 1cpp.dll, для начала.
11. Anics (anics) 27.05.09 10:32 Сейчас в теме
1cpp.dll загружается, ошибка остается
12. Ёпрст Биомать, а? Верните бесплатный доступ к файлам! (Ёпрст) 1010 27.05.09 10:33 Сейчас в теме
13. Anics (anics) 27.05.09 10:34 Сейчас в теме
14. Anics (anics) 27.05.09 10:47 Сейчас в теме
15. Ёпрст Биомать, а? Верните бесплатный доступ к файлам! (Ёпрст) 1010 27.05.09 10:59 Сейчас в теме
16. Anics (anics) 27.05.09 11:07 Сейчас в теме
и с 3.0.1.22 не работает. Вк загружается, в примере же прописывется ее вызов.
17. Ёпрст Биомать, а? Верните бесплатный доступ к файлам! (Ёпрст) 1010 27.05.09 11:12 Сейчас в теме
18. Ёпрст Биомать, а? Верните бесплатный доступ к файлам! (Ёпрст) 1010 27.05.09 11:14 Сейчас в теме
(16) На закладке в 1с-предприятие, в Помощь о программе, появилась вкладка с ВК ?
19. Anics (anics) 27.05.09 11:21 Сейчас в теме
Заработала. Надо было Вк вызывать не в процедуре ПриОткрытии() обработки,
а в процедуре ПриНачалеРаботыСистемы().
20. Ёпрст Биомать, а? Верните бесплатный доступ к файлам! (Ёпрст) 1010 27.05.09 11:24 Сейчас в теме
(19) это без разницы... можно хоть в Табло в самом предприятии написать строчку ЗагрузитьВнешнююКомпоненту("1cpp.dll") ...
21. Антон (anton.fly7) 134 04.10.09 13:56 Сейчас в теме
Привет!
только начинаю упражняться с прямыми запросами...
скажите, в этой строке

|UPPER("+ТекПоле+") Like '%' + :Стр + '%'";

что должно быть написано? я так понел что косяк какой то...
22. Антон (anton.fly7) 134 04.10.09 14:03 Сейчас в теме
23. Антон (anton.fly7) 134 06.10.09 14:37 Сейчас в теме
почему то не ищет по наименованию по русским буквам... :?:
24. Алексей Плутенко (Noy) 1053 06.10.09 15:10 Сейчас в теме
(23) у меня ищет...
база скульная? функцию покажи...
25. Алексей Плутенко (Noy) 1053 06.10.09 15:15 Сейчас в теме
(23) Вижу на мисте уже ответили ;)
26. Антон (anton.fly7) 134 06.10.09 15:17 Сейчас в теме
опять разобрался...
передавал на поиск маленькими буквами, а в запросе приводися к большим буквам
27. Антон (anton.fly7) 134 06.10.09 15:18 Сейчас в теме
"UPPER(" + ТекПоле + ") Like '%' + :Стр" + Строка(i) + " + '%'"
28. Алексей Плутенко (Noy) 1053 06.10.09 15:25 Сейчас в теме
"UPPER(" + ТекПоле + ") Like '%'" + ВРЕГ(Строка(i)) + "'%'"
29. selesta (selesta) 14 18.06.12 01:47 Сейчас в теме
вещь супер, на 600 тыс. справочнике результат на 2 секунде
спасибо за простоту и универсальность!
30. selesta (selesta) 14 03.07.12 14:04 Сейчас в теме
добавлю еще - не работает поиск с апострофом (одинарной кавычкой)
нужно заменить ее на 2
ИскомаяСтрока = СтрЗаменить(ИскомаяСтрока,"'","''");
31. Алексей Плутенко (Noy) 1053 03.07.12 14:30 Сейчас в теме
(30) никто не совершенен. Баги в ПО будут всегда :)