7.7 Отсев элементов справочника в запросе по тегам

Тема в разделе "Конфигурирование на платформе "1С:Предприятие 7.7"", создана пользователем Asttoxa, 4 июн 2012.

  1. TopicStarter Overlay
    Asttoxa
    Offline

    Asttoxa Опытный в 1С

    Регистрация:
    18 май 2010
    Сообщения:
    525
    Симпатии:
    0
    Баллы:
    26
    Добрый день.
    Подскажите пожалуйста как сделать.
    Требуется по обязательному слову и строке поиска (теги), например: "Тонер 1010 1012" запросом отсеять все номенклатурные позиции, которые возможно включают в себя эти слова.

    Тоесть с обязательным словом "Тонер" и тегами "1010 1012" в список попадут элементы с наименованием:
    "Тонер 1010"
    "Тонер 1012"
    "Тонер 1010/1012"

    И не попадают:

    "Тонер"
    "Тонер 1011"
    "1010"

    У меня максимум, что получилось это вот так:
    Код:
    Процедура ПоискВозможныхАналогов()
    Перем Запрос, ТекстЗапроса, ВставкаВзапрос;
    
    СписокВозможныхАналогов.УдалитьВсе();
    
    Если ПустоеЗначение(ОсновноеКлючевоеСлово)=1 Тогда
    Возврат;
    КонецЕсли; 
    
    //Создание объекта типа Запрос
    Запрос = СоздатьОбъект("Запрос");
    ТекстЗапроса =
    "//{{ЗАПРОС(ЗаполнениеСпискаВозможныхАналогов)
    |ОбрабатыватьДокументы все;
    |Обрабатывать НеПомеченныеНаУдаление;
    |Номенклатура = Справочник.Номенклатура.ТекущийЭлемент;
    |Наименование = Справочник.Номенклатура.Наименование;
    |Группировка Номенклатура без групп;
    |Условие(Найти(СокрЛП(нрег(Наименование)),СокрЛП(нрег(ОсновноеКлючевоеСлово)))=1);
    |Условие(СписокАналогов.Принадлежит(Номенклатура)=0);
    |Условие(ПустоеЗначение(Номенклатура.Аналоги)=1);
    |"//}}ЗАПРОС
    ;
    
    
    Если (ПустоеЗначение(Слово1)=0)или(ПустоеЗначение(Слово2)=0)или
    (ПустоеЗначение(Слово3)=0)или(ПустоеЗначение(Слово4)=0) Тогда
    
    
    ВставкаВзапрос="";
    
    Если ПустоеЗначение(Слово1)=0 Тогда
    ВставкаВзапрос="(СтрЧислоВхождений(СокрЛП(нрег(Наименование)),СокрЛП(нрег(Слово1)))>0)"
    КонецЕсли;					
    
    Если ПустоеЗначение(Слово2)=0 Тогда
    Если ПустоеЗначение(ВставкаВзапрос)=0 Тогда
    ВставкаВзапрос=ВставкаВзапрос+"или";
    КонецЕсли;
    ВставкаВзапрос="(СтрЧислоВхождений(СокрЛП(нрег(Наименование)),СокрЛП(нрег(Слово2)))>0)"
    КонецЕсли;
    
    Если ПустоеЗначение(Слово3)=0 Тогда
    Если ПустоеЗначение(ВставкаВзапрос)=0 Тогда
    ВставкаВзапрос=ВставкаВзапрос+"или";
    КонецЕсли;
    ВставкаВзапрос="(СтрЧислоВхождений(СокрЛП(нрег(Наименование)),СокрЛП(нрег(Слово3)))>0)"
    КонецЕсли;
    
    Если ПустоеЗначение(Слово4)=0 Тогда
    Если ПустоеЗначение(ВставкаВзапрос)=0 Тогда
    ВставкаВзапрос=ВставкаВзапрос+"или";
    КонецЕсли;
    ВставкаВзапрос="(СтрЧислоВхождений(СокрЛП(нрег(Наименование)),СокрЛП(нрег(Слово4)))>0)"
    КонецЕсли;
    ТекстЗапроса=ТекстЗапроса+"Условие("+ВставкаВзапрос+");"; 
    
    КонецЕсли;
    
    Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
    Возврат;
    КонецЕсли;
    Пока Запрос.Группировка(1) = 1 Цикл
    СписокВозможныхАналогов.ДобавитьЗначение(Запрос.Номенклатура); 
    КонецЦикла;
    КонецПроцедуры
    
    Выглядит ужасно, и работает кривовато :(

    Спасибо.
  2. WaRDeR
    Offline

    WaRDeR Модераторы Команда форума Модератор

    Регистрация:
    23 ноя 2006
    Сообщения:
    3.263
    Симпатии:
    14
    Баллы:
    29
    Для отбора по такому условию делать запрос смысла нет, прироста скорости не будет.
    Поэтому, лучше делать запрос без этого условия, выгружать в ТЗ, а потом ТЗ уже фильтровать.

    Что касается конкретно алгоритма отбора, то из приведенного примера не совсем понятно, как он должен работать.
  3. Бухгалтерский угодник
    Offline

    Бухгалтерский угодник Администраторы Команда форума Администратор

    Регистрация:
    29 дек 2008
    Сообщения:
    21.520
    Симпатии:
    407
    Баллы:
    104
    Если предположить что тэги находяся в СпискеЗначений, то вот функция
    Код:
    //ТМЦ - наименование номенклатуры
    //СтрПоиска - основная строка поиска
    //Тэги - СписокЗначений
    //1 - все найдено; 0 - что-то не сраслось
    Функция НайтиСоотвествия(ТМЦ,СпрПоиска,Тэги)
    ТМЦ=ВРег(ТМЦ);
    Вхождения=0;
    Для к=1 По Тэги.РазмерСписка() Цикл
    Вхождения=Вхождения+?(Найти(ТМЦ,ВРег(Тэги.ПолучитьЗначение(к))<>0,1,0);
    КонецЦикла;
    Возврат ?((Найти(ТМЦ,ВРег(ТСпрПоиска)<>0)И(Вхождения<>0),1,0);
    КонецФункции
    
    ею и отсеивайте.... Количество тэгов не ограничено
  4. TopicStarter Overlay
    Asttoxa
    Offline

    Asttoxa Опытный в 1С

    Регистрация:
    18 май 2010
    Сообщения:
    525
    Симпатии:
    0
    Баллы:
    26
    Ну у меня в номенклатуре порядка 8к-9к позиций и перебирать их запросом гораздо быстрее чем перебором

    Это все понятно. Но проблема в том что это нужно использовать в Запросе! :( Перебором слишком долго будет лопатить справочник номенклатуры :(
  5. Бухгалтерский угодник
    Offline

    Бухгалтерский угодник Администраторы Команда форума Администратор

    Регистрация:
    29 дек 2008
    Сообщения:
    21.520
    Симпатии:
    407
    Баллы:
    104
    Так и используйте в запросе))))))))))) Конечно применение ВНЕШНЕЙ функции сильно замедлит запрос. Но если нет иного выхода....
  6. TopicStarter Overlay
    Asttoxa
    Offline

    Asttoxa Опытный в 1С

    Регистрация:
    18 май 2010
    Сообщения:
    525
    Симпатии:
    0
    Баллы:
    26
    Сильно замедлит не на столько же, чтобы использовать перебор в большом справочнике?
  7. TopicStarter Overlay
    Asttoxa
    Offline

    Asttoxa Опытный в 1С

    Регистрация:
    18 май 2010
    Сообщения:
    525
    Симпатии:
    0
    Баллы:
    26
    Кнопочка редактировать пропала :(

    Можно не отвечать я с помощью функции_GetPerformanceCounter() и то и другое замерял запросом хоть и медленнее, но быстрее перебором в два раза!

    Спасибо!
  8. TopicStarter Overlay
    Asttoxa
    Offline

    Asttoxa Опытный в 1С

    Регистрация:
    18 май 2010
    Сообщения:
    525
    Симпатии:
    0
    Баллы:
    26
    В продолжение темы:
    Как из строки с тегами загрузить в Список? С запятыми заморачиваться не хочется, чтобы опечатку не допустили люди.
    Тоесть тэги в строке разделены пробелами.
    Строка должна выглядеть примерно так: "Тэг1 Тэг2 тэг3"
  9. TopicStarter Overlay
    Asttoxa
    Offline

    Asttoxa Опытный в 1С

    Регистрация:
    18 май 2010
    Сообщения:
    525
    Симпатии:
    0
    Баллы:
    26
    Сам с собой веду беседу :)

    Вот что придумал по этому поводу:
    Код:
    Функция ПеревестиСтроку()
    Перем Спис,НачТочка, КолЗнаков, Рез;
    Спис=СоздатьОбъект("СписокЗначений");
    Спис2=СоздатьОбъект("СписокЗначений");
    Если ПустоеЗначение(СтрокаТэгов)=1 Тогда
    Возврат Спис;
    КонецЕсли;
    НачТочка=0;
    Для к=1 по СтрДлина(СтрокаТэгов) Цикл
    Если Сред(СтрокаТэгов,к,1)=" " Тогда
    КолЗнаков=к-НачТочка;
    Спис.ДобавитьЗначение(Сред(СтрокаТэгов,НачТочка,КолЗнаков));
    НачТочка=к;
    КонецЕсли;
    КонецЦикла;				 
    
    Спис.ДобавитьЗначение(Прав(СтрокаТэгов,СтрДлина(СтрокаТэгов)-НачТочка));
    
    Для к=1 по Спис.РазмерСписка() Цикл
    Если ПустоеЗначение(СокрЛП(Спис.ПолучитьЗначение(к)))=0 Тогда
    Спис2.ДобавитьЗначение(Врег(СокрЛП(Спис.ПолучитьЗначение(к))));
    КонецЕсли;
    КонецЦикла;
    
    Возврат Спис;
    КонецФункции
    Может кому пригодится, или подкорректирует кто нить. Но функция работает :)

Поделиться этой страницей