Отбор элементов справочника по строковым реквизитам через прямой запрос. Универсально, для 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 '%' + :Стр + '%'";
ИначеЕсли Метод=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 — затем клавишу «Я» и при зажатой клавишу «Я» набирает последние цифры штрихкода — справочник мгновенно фильтруется. При отжатии клавиши «Я» фильтр сбрасывается, а курсор активизируется на элемент, который был активен при фильтре — мои юзеры просто в восторге… 🙂
В качестве демонстрации прикладываю обработку, демонстрирующую работу функции.
Статья расчитана в первую очередь на тех, кто хочет быстро попробовать — что же это за зверь — «прямой запрос».
P.S. В базах DBF будет работать только в разделенном режиме.
(1) при помощи правки dbeng32 от hogik работает в любом…
+2 всё это конечно хорошо, но вот решение, имхо , получшее:
http://www.1cpp.ru/forum/YaBB.p
(3) Не получшее, а лучше просто в разы!
Ясень пень, что моя маленькая заготовка с ней не сравниться, но как обучающий материал пойдет.
(4) ну ясно…и это , к (2) тоже приглядись, если что на будующее…
+5http://infostart.ru/projects/2418/
(5,6) Спасибо.
плюсанул за идею, сам видимо пользоваться не буду
Что с этим делать?
МИК=СоздатьОбъект(«MetaInfoClasses»);
{C:DOCUMENTS AND SETTINGSАДМИНИСТРАТОРРАБОЧИЙ СТОЛFN_FINDSPR.ERT(23)}: Неудачная попытка создания объекта (MetaInfoClasses)
(9) загрузить ВК 1cpp.dll, для начала.
1cpp.dll загружается, ошибка остается
(11) версия 1сpp.dll какая ?
2.0.3.1
с 2.5.0.7 то же самое
(14)http://www.1cpp.ru/images/3/32/Icpp-latest.rar
а с этой ?
А вк точно загружена ?
и с 3.0.1.22 не работает. Вк загружается, в примере же прописывется ее вызов.
(16) Другие ВК есть?
(16) На закладке в 1с-предприятие, в Помощь о программе, появилась вкладка с ВК ?
Заработала. Надо было Вк вызывать не в процедуре ПриОткрытии() обработки,
а в процедуре ПриНачалеРаботыСистемы().
(19) это без разницы… можно хоть в Табло в самом предприятии написать строчку ЗагрузитьВнешнююКомпоненту(«1cpp.dll») …
Привет!
только начинаю упражняться с прямыми запросами…
скажите, в этой строке
|UPPER(«+ТекПоле+») Like '%' + :Стр + '%'»;
что должно быть написано? я так понел что косяк какой то…
разобрался 😳
почему то не ищет по наименованию по русским буквам… ❓
(23) у меня ищет…
база скульная? функцию покажи…
(23) Вижу на мисте уже ответили 😉
опять разобрался…
передавал на поиск маленькими буквами, а в запросе приводися к большим буквам
«UPPER(» + ТекПоле + «) Like ‘%’ + :Стр» + Строка(i) + » + ‘%'»
«UPPER(» + ТекПоле + «) Like ‘%'» + ВРЕГ(Строка(i)) + «‘%'»
вещь супер, на 600 тыс. справочнике результат на 2 секунде
спасибо за простоту и универсальность!
добавлю еще — не работает поиск с апострофом (одинарной кавычкой)
нужно заменить ее на 2
ИскомаяСтрока = СтрЗаменить(ИскомаяСтрока,»‘»,»»»);
(30) никто не совершенен. Баги в ПО будут всегда 🙂