Имя: Пароль:
1C
1C 7.7
v7: Помогите с запросом!
0 oslokot
 
01.08.12
19:43
Имеем обычный запрос к справочнику "Номенклатура"
В запросе нужен фильтр (условие то бишь) по наименованию номенклатуры такого типа:
В поле ввода (обычная строка) пользователем указываются через разделитель ";" имена товаров и нужно чтобы запрос вывел именно эти указанные номенклатурные позиции. Например:
Хлеб;Вино;Мороженое
Запрос выводит в таблицу всю номенклатуру где есть такие слова.
Как это сделать?
1 Oleg_Kag
 
01.08.12
19:52
2 mihco
 
01.08.12
19:53
Разделить строку на слова через СтрЗаменить, и в запрос условия через "ИЛИ": (Найти(Наименование, Слово[1]) > 0) ИЛИ (Найти(Наименование, Слово[2]) > 0) ИЛИ ....
3 Злопчинский
 
01.08.12
20:01
////////////////////////////////////////////////////////////////////////////////
// ПРОЦЕДУРЫ И ФУНКЦИИ МОДУЛЯ
//
//******************************************************************************
// ПоискПоПодстроке()
//
// Параметры:
//  Нет
//
// Возвращаемое значение:
//  Нет
//
// Вызывается из формул элементов диалога
//  Поле ввода подтстроки поиска
//
// Описание:
//  Производит поиск элементов по подстроке, заполняя найденными значениями
//  таблицу значений формы обработки.
//
Процедура ПоискПоПодстроке()
   
   Элементы.УдалитьСтроки();
   Если ПустоеЗначение(ПодСтрокаПоиска) = 1  Тогда
       Предупреждение("Не задана подстрока для поиска...      ", 20);
       Возврат;
   КонецЕсли;
   
   РеквизитПоиска = СокрЛП(СписокРеквизитовПоиска.ПолучитьЗначение(СписокРеквизитовПоиска.ТекущаяСтрока()));

   Если ВидСправочника="Номенклатура"
   Тогда //только для спр.номенклатура
       Если РеквизитПоиска="Наименование"
       Тогда //только поиск по наименованию
           Если ПоискПоПодстрокеSQlite()=1
           Тогда //поиск прошел успешно
               Возврат;
           КонецЕсли;
       КонецЕсли;    
   КонецЕсли;        

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

   РазбиваемаяСтрока    = ПодСтрокаПоиска;    
   РазбиваемаяСтрока    = СтрЗаменить(РазбиваемаяСтрока,"'","");
   РазбиваемаяСтрока    = СтрЗаменить(РазбиваемаяСтрока,"""","");
   РазбиваемаяСтрока    = СтрЗаменить(СокрЛП(РазбиваемаяСтрока)," ",РазделительСтрок);
   
   ТекстЗапроса ="
   |Без Итогов;
   |ТекущийЭлемент = Справочник.*.ТекущийЭлемент;" +
   РеквизитПоиска + " = Справочник.*." + РеквизитПоиска + ";
   |Группировка ТекущийЭлемент Без Упорядочивания Без Групп;";
   
   Для Индекс = 1 По СтрКоличествоСтрок(РазбиваемаяСтрока)
   Цикл Слово = ВРег(СтрПолучитьСтроку(РазбиваемаяСтрока,Индекс));
       
       Если  ПустоеЗначение(Слово)=1
       Тогда Продолжить;
       КонецЕсли;    
       ТекстЗапроса = ТекстЗапроса+"
       |Условие(Найти(ВРег(" + РеквизитПоиска + "),"""+Слово+""")>0);";
   КонецЦикла;
   
   ТекстЗапроса=СтрЗаменить(ТекстЗапроса,"*",ВидСправочника);
   
   Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
       Возврат;
   КонецЕсли;

   Инд=0;
   Состояние("Обработано ");
   Пока Запрос.Группировка() = 1 Цикл
       Инд=Инд+1;
       Если Инд%100=0 Тогда
           Состояние("Обработано "+Инд);
       КонецЕсли;
       
       ТекЭлемент = Запрос.ТекущийЭлемент;
       Элементы.НоваяСтрока();
       Сообщить(""+ТекЭлемент+" "+ТекЭлемент.Артикул);
       Элементы.Пометка    = ТекЭлемент.wms_Активен +1;        
       Элементы.Элемент    = ТекЭлемент;
       
       // Заполним колонки
       СчетчикЦикла = 0;
       Для СчетчикЦикла = 1 По СписокРеквизитовПоиска.РазмерСписка() Цикл
           ТекРеквизит   =  СокрЛП(СписокРеквизитовПоиска.ПолучитьЗначение(СчетчикЦикла));
           Элементы.УстановитьЗначение(Элементы.НомерСтроки, ТекРеквизит, СокрЛП(ТекЭлемент.ПолучитьАтрибут(ТекРеквизит)));
       КонецЦикла;
       
   КонецЦикла;
   
   Состояние("Обработано "+Инд);
   
   Форма.Открыть.Доступность(?(Элементы.КоличествоСтрок()>0,1,0));
   Форма.Выбрать.Доступность(?(Элементы.КоличествоСтрок()>0,1,0));
   
   // попытаемся найти подстроку в списке
   Поз    = СписокВведенныхПодстрок.НайтиЗначение(ПодСтрокаПоиска);
   Если Поз > 0 Тогда
       // сместим значение в начало списка
       СписокВведенныхПодстрок.СдвинутьЗначение(1 - Поз, Поз);
   Иначе
       // добавим подстроку в начало списока
       СписокВведенныхПодстрок.ВставитьЗначение(1, ПодСтрокаПоиска);
       
       Пока СписокВведенныхПодстрок.РазмерСписка() > 15 Цикл
           СписокВведенныхПодстрок.УдалитьЗначение(СписокВведенныхПодстрок.РазмерСписка());
       КонецЦикла;
           
   КонецЕсли;
   
   Попытка Активизировать("Элементы");
   Исключение
   КонецПопытки;
   
КонецПроцедуры // ПоискПоПодстроке()
4 Злопчинский
 
01.08.12
20:02
//======================================================================
Функция ПоискПоПодстрокеSQlite()
   
   //если здесь - значит на периферии
   //примем административное правило, на периферии - ДБФ базы    
   Попытка
       глВКлайт.Открыть(":memory:");
       Запрос = глВКлайт.НовыйЗапрос();
       Запрос.ВыполнитьЗапрос("create virtual table Товары using dbeng(Справочник.Номенклатура)");
   Исключение
       //тОшибка = "инфо: проблема при выполнении запроса инициализации вирт.таблицы, при случае - сообщите программисту: "+ОписаниеОшибки();
       //Сообщить(тОшибка);
       Возврат 0;
   КонецПопытки;    

   //ОТЛАДКА
   //Сообщить("работаем SQLite");
   
   РазбиваемаяСтрока    = ПодСтрокаПоиска;    
   РазбиваемаяСтрока    = СтрЗаменить(РазбиваемаяСтрока,"'","");
   РазбиваемаяСтрока    = СтрЗаменить(РазбиваемаяСтрока,"""","");
   РазбиваемаяСтрока    = СтрЗаменить(СокрЛП(РазбиваемаяСтрока)," ",РазделительСтрок);
   
   ТекстЗапроса = "SELECT
   |Товары.id [Элемент :Справочник.Номенклатура]
   |FROM Товары
   |WHERE Товары.isfolder=2 and Товары.ismark <> '*'";    

   Для Индекс = 1 По СтрКоличествоСтрок(РазбиваемаяСтрока)
   Цикл Слово = Врег(СтрПолучитьСтроку(РазбиваемаяСтрока,Индекс));
       
       Если  ПустоеЗначение(Слово)=1
       Тогда Продолжить;
       КонецЕсли;    
       ТекстЗапроса = ТекстЗапроса+"
       |AND UPPER(Товары.descr) LIKE '%"+Слово+"%'";
   КонецЦикла;
   
   //ТекстЗапроса = ТекстЗапроса+"
   //|ORDER BY Элемент.descr";
   
   ТЗраб = СоздатьОбъект("ТаблицаЗначений");
   Попытка
       _время1 = _GetPerformanceCounter();
       Запрос.ВыполнитьЗапрос(ТекстЗапроса).Выгрузить(ТЗраб);
       //Сообщить((_GetPerformanceCounter()-_время1)/1000);
       //ч=1/0;
   Исключение
       глВКлайт.Закрыть();
       тОшибка = "ошибка при выполнении запроса, сообщите программисту: "+ОписаниеОшибки();
       Сообщить(тОшибка);
       Возврат 0;
   КонецПопытки;
   глВКлайт.Закрыть();

   Инд=0;
   Состояние("Обработано ");
   ТЗраб.ВыбратьСтроки();
   Пока ТЗраб.ПолучитьСтроку() = 1
   Цикл Инд=Инд+1;
       
       Если  Инд%100=0
       Тогда Состояние("Обработано "+Инд);
       КонецЕсли;
       
       ТекЭлемент = ТЗраб.Элемент;
       Если Найти(ВРег(ТекЭлемент.ПолноеНаименование()),"НЕ ИСПОЛЬЗОВАТЬ") = 0
       Тогда //помещаем
       Иначе //мусор!
           Продолжить;
       КонецЕсли;
       
       Элементы.НоваяСтрока();
       Элементы.Пометка    = ТекЭлемент.wms_Активен +1;
       Элементы.Элемент    = ТекЭлемент;
       ЦенаТекНоменклатуры    = "";
       ОстатокТекНоменклатуры    = "";
       
       ЦенаТекНоменклатуры = глПолучитьЦену(ТекЭлемент, глЗначениеПоУмолчанию("ОсновнойТипЦенПродажи"), РабочаяДата(), ТекЭлемент.БазоваяЕдиница, глРубли,1);
       ЦенаТекНоменклатуры = глФРМ(ЦенаТекНоменклатуры);
       локРегистрОтстаткиТМЦ.УстановитьЗначениеФильтра("Номенклатура",ТекЭлемент,1);
           
       ТаблОстатков = ""; локРегистрОтстаткиТМЦ.ВыгрузитьИтоги(ТаблОстатков);
       ТаблОстатков.Свернуть("Номенклатура","Количество");
       ОстатокТекНоменклатуры = ТаблОстатков.Итог("Количество");

       Элементы.Цена     = ЦенаТекНоменклатуры;
       Элементы.Остаток = ОстатокТекНоменклатуры;
         
       // Заполним колонки
       СчетчикЦикла = 0;
       Для СчетчикЦикла = 1 По СписокРеквизитовПоиска.РазмерСписка() Цикл
           ТекРеквизит   =  СокрЛП(СписокРеквизитовПоиска.ПолучитьЗначение(СчетчикЦикла));
           Элементы.УстановитьЗначение(Элементы.НомерСтроки, ТекРеквизит, СокрЛП(ТекЭлемент.ПолучитьАтрибут(ТекРеквизит)));
       КонецЦикла;
       
   КонецЦикла;
   
   Состояние("Обработано "+Инд);
   
   Форма.Открыть.Доступность(?(Элементы.КоличествоСтрок()>0,1,0));
   Форма.Выбрать.Доступность(?(Элементы.КоличествоСтрок()>0,1,0));
   
   // попытаемся найти подстроку в списке
   Поз    = СписокВведенныхПодстрок.НайтиЗначение(ПодСтрокаПоиска);
   Если  Поз > 0
   Тогда // сместим значение в начало списка
       СписокВведенныхПодстрок.СдвинутьЗначение(1 - Поз, Поз);
   Иначе
       // добавим подстроку в начало списока
       СписокВведенныхПодстрок.ВставитьЗначение(1, ПодСтрокаПоиска);
       Пока  СписокВведенныхПодстрок.РазмерСписка() > 15
       Цикл  СписокВведенныхПодстрок.УдалитьЗначение(СписокВведенныхПодстрок.РазмерСписка());
       КонецЦикла;
           
   КонецЕсли;
   
   НовыйЭлемент    = "";
   Количество        = 1;  
   Цена            = 0;
   Элементы.ТекущаяКолонка("Наименование");
   Возврат 1;
КонецФункции //ПоискПоПодстрокеSQlite()
5 oslokot
 
01.08.12
20:57
ок, спасибо! сделал так:
СтрокаСодержит = Содержит;
Для Номер = 1 По СтрЧислоВхождений(СтрокаСодержит, ";") Цикл
   Значение = СтрокаСодержит;
   Если Найти(Значение, ";") > 0 Тогда
       Значение = Сред(Значение, 1, Найти(Значение, ";") - 1);
       СтрокаСодержит  = Сред(СтрокаСодержит, Найти(СтрокаСодержит, ";") + 1);
       ТекстЗапроса = ТекстЗапроса+"
   |Условие(Найти(ВРег(Наименование),"""+ВРег(Значение)+""")>0);";
   КонецЕсли;
КонецЦикла;

Заработало!

А как еще сделать 2 условия:
Содержит Хлеб;Вино;Мороженое
НеСодержит Испанское;

?
п.с. а как в этом форуме коды вставлять?
6 Злопчинский
 
01.08.12
21:24
найти(Где,"испансоке")=0
в прямом запрсое наверное что-то типа NOT для like - тут я не спец
7 Злопчинский
 
01.08.12
21:25
прсото тупо код вставляешь и все. сам распознается
8 Злопчинский
 
01.08.12
21:26
в "значении" наверное надо пробелы ВОЗМОЖНО обрамляющие слово - убрать...?
9 oslokot
 
01.08.12
23:27
(8) Ага, спасибо! вроде получилось