Страницы: 1
RSS
Поиск номера позиции элемента, заданного по маске, в массиве
 
Доброго времени суток, уважаемые форумчане. Снова обращаюсь в вам за АЛЬТЕРНАТИВНЫМ решением задачи для самообразования. Итак ситуация: имеется массив данных: Arr_fuel = Array("бензин", "топливо", "газ"). Требуется проверить содержимое активной ячейки на совпадение с элементами массива, при этом содержимое ячейки может иметь вид "Газ углеводородный СПБТ", но главное слово здесь это газ, проверять на совпадения нужно по маске и такой вариант должен считаться как совладение. При этом для дальнейших расчетов требуется запомнить номер элемента найденного совпадения в массиве. Сейчас все это РАБОТАЕТ так:
Код
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
    Arr_fuel = Array("бензин", "топливо", "газ")
    For j = 0 To UBound(Arr_fuel)
        If UCase(ActiveCell.Value) Like UCase("*" & Arr_fuel(j) & "*") Then Exit For
    Next j
                    
    If j <= UBound(Arr_fuel) Then
        x = Range("A1:C" & Cells(Rows.Count, 1).End(xlUp).Row).Value
                            
        For i = 1 To UBound(x)
            If UCase(x(i, 1)) Like UCase("*" & Arr_fuel(j) & "*") Then MsgBox "ДА  " & Arr_fuel(j)
        Next i
    Else: MsgBox "НЕТ"
    End If
End Sub
А вопрос у меня такой: можно ли найти значение j БЕЗ использования цикла. Повторюсь, рабочее решение у меня есть, просто хотелось бы узнать о возможности альтернативного решения, чисто для опыта. Если такого решения нет, ничего страшного, нет так нет.
Заранее спасибо всем откликнувшимся
 
Цитата
узнать о возможности альтернативного решения,
UDF
Код
Function iToplivo(cell$) As String
Dim i As Integer
 With CreateObject("VBScript.RegExp")
   .Global = True
   .ignorecase = True
      .Pattern = "бензин|топливо|газ"
      If .test(cell) Then
       iToplivo = "Да это: " & .Execute(cell)(0)
      End If
 End With
End Function
 
Спасибо, Kuzmich. Это регулярные выражения называется, да? А если мне не в функции пользователя надо, а просто в коде,  то по аналогии со словарем надо будет задать имя и указать параметры:?
 
Код
Sub iToplivo_()
Dim i As Long
Dim iLastRow As Long
 iLastRow = Cells(Rows.Count, 1).End(xlUp).Row
 With CreateObject("VBScript.RegExp")
   .Global = True
   .ignorecase = True
   .Pattern = "бензин|топливо|газ"
   For i = 2 To iLastRow
      If .test(Cells(i, "A")) Then
       Cells(i, "B") = "Да это: " & .Execute(Cells(i, "A"))(0) _
                   & " номер позиции: " & .Execute(Cells(i, "A"))(0).FirstIndex + 1
      End If
   Next
 End With
End Sub
Изменено: Kuzmich - 19.03.2021 10:48:17 (добавил номер позиции)
 
Еще раз спасибо за Ваш вариант
 
Можно использовать Find Method объекта Range, хотя без циклов вообще не обойдешься наверно.
Код
Sub Poisk()
Dim Rg1 As Range, Rg2 As Range, Rg3 As Range, Adres$, strPoisk$
    strPoisk = "*Газ*" 'If strPoisk = "" Then Exit Sub
Set Rg1 = Cells(1).CurrentRegion
    Set Rg2 = Rg1.Cells.Find(strPoisk, , xlValues, xlWhole)
If Not Rg2 Is Nothing Then
    Adres = Rg2.Address
    Set Rg3 = Rg2
        Do
        Set Rg3 = Union(Rg3, Rg2)
        Set Rg2 = Rg1.Cells.FindNext(After:=Rg2)
        Loop Until Rg2.Address = Adres
    Rg3.Select
End If
End Sub
И здесь есть цикл. и еще надо один ввести по массиву искомых значений. Здесь только поиск по значению <<Газ>>
В ссылке Rg3 получаете диапазон ячеек содержащих <<Газ>>
 
Спасибо и вам, Евгений, но я как раз и пытаюсь (чисто для опыта) избежать цикла. Хотелось бы уточнить вот что: используя регулярные выражения, предложенные Kuzmich, я столкнулся с такой закавыкой. Для проверки кода создадим массив и проверим его значения:
Код
Arr = Array("Бензин АИ-92", "бензиновый очиститель", "Газ углеводородный СПБТ", "керогаз")
Set reFuel = CreateObject("VBScript.RegExp"): reFuel.Global = True: reFuel.ignorecase = True
    reFuel.Pattern = "бензин|топливо|газ" 'шаблон
    For i = 0 To UBound(Arr)
        If reFuel.test(Arr(i)) Then MsgBox "ДА" & " " & Arr(i)
    Next i
Если запустить этот код, то положительный ответ будет для всех 4 слов, входящих в массив, а должен быть только для 1 и 3. Как следует задать шаблон, чтобы (в данном случае) положительный ответ был для любого выражения, содержащего слова: "бензин" ,"топливо" или "газ" в сочетании с любыми другими словами или словом и отрицательный ответ для вариантов типа "керогаз" или "топливный элемент"?
Заранее спасибо за помощь.
 
OlegO Извините но я  не умею писать как Kuzmich это надо у него спрашивать
 
Для вашего примера - добавьте в pattern пробелы в конце слова.
Если же массив будет другой, возможны варианты.
 
Цитата
RAN написал:
добавьте в pattern пробелы
Тёзка, а если это начало/конец строки или символы.,!-()?"«» - их по боку? Ладно ТС начинающий, но вы-то уже ого-го-го! :)
 
Владимир (ZVI) в теме https://www.planetaexcel.ru/forum/index.php?PAGE_NAME=read&FID=1&TID=119086 предлагал
маленький трюк  с "\b", чтобы работало не только с англо-словами
но я что-то не могу осилить
Изменено: Kuzmich - 19.03.2021 13:38:38
 
Тёзка, привет.
Дык я же написал
Цитата
RAN написал:
Для вашего примера
Цитата
RAN написал:
массив будет другой, возможны варианты
:)
 
Уважаемые гуру, дык мне то как написать шаблон, чтобы работало правильно?

RAN, пробелы в конце помогли и скорее всего этого будет достаточно, спасибо, но для варианта "дизельное топливо" ответ будет неверен (для обратной последовательности правильно), а если и до начала слова поставить пробел, тогда не пройдет 3 вариант примера
 
пробуйте:
Код
.Pattern = "(^|[ \s])(бензин|топливо|газ)([.!?:, \s]|$)"
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Спасибо, Ігор Гончаренко большое. Работает правильно, теперь самое главное научиться самому формировать такие шаблоны
 
OlegO,  спрашивал
Цитата
Поиск номера позиции элемента
Ігор Гончаренко, написал
пробуйте:
Код
.Pattern = "(^|[ \s])(бензин|топливо|газ)([.!?:, \s]|$)"

Ігор. Как правильно определить начальную позицию?
 
Код
(^|[ \s])
искомое слово может быть в начале строки
или
перед ним может быть что угодно - только не буква, видимо, кириллическая
и тогда это лучше написать так:
Код
(^|[^а-яА-ЯёЁ]) 
потому что в строке "(бензин, керосин)" первая маска бензин не найдет((( , а тут же явно речь о бензине
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Ігор. Я спрашивал: Как правильно определить начальную позицию через FirstIndex?
 
допустим m - это найденное совпадение
тогда
начальная позиция нужного слова  
Код
= m.FirstIndex + 1 + len(m.SubMatches(1))
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Ігор Гончаренко,
Мы же ищем начальную позицию, причем тут
Код
+ len(m.SubMatches(1))

может надо
Код
+ len(m.SubMatches(0))
Изменено: Kuzmich - 20.03.2021 22:16:01
 
да, очевидно (а в чем был вопрос, если ответ очевиден и без ответа))
Изменено: Ігор Гончаренко - 20.03.2021 23:05:59
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Ігор Гончаренко,
Можно ли обратиться к m.SubMatches(1) как к объекту?
и в (^|[ \s]) зачем рядом пробел (символ 32) и пробельный знак \s ?
 
m - это обьект
m.SubMatches(1) - это строка (это можно посмотреть в окне Locals, в колонке Type)
а \s - в литературе где-то попалось "пробельные символы" это один из 5 символов: новая страница, новая строка, перевод каретки, горизонтальная табуляция, вертикальная табуляция, а вот пробел не входит в число "пробельных символов"(( вместо \s можно написать  [\f\n\r\t\v] (эти 5 символов), но набирать руками 10 знаков или 2 - конечно я выберу 2
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Ігор Гончаренко, написал
Цитата
а вот пробел не входит в число "пробельных символов"
Мама мыла раму
Код
.Pattern = "[^\s]+"

в объекте mo три слова
 
да, на сайте написано одно
а по факту пробел тоже входит (подтвердился давний принцип - нужно все проверять на собственном опыте - это самый надежный критерий, что прочитанное понято правильно и работает так, как написано)
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
OFF
Цитата
Ігор Гончаренко: на сайте написано одно
обычно по RegExp смотрю тут и пока косяков не замечал…
Цитата
Ігор Гончаренко: нужно все проверять на собственном опыте - это самый надежный критерий, что прочитанное понято правильно и работает так, как написано
полностью согласен - неоднократно проверенное утверждение
Изменено: Jack Famous - 22.03.2021 09:09:31
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Jack Famous,
Цитата
Jack Famous написал:
 тут  и пока косяков не замечал…
отличный пример, прямо не в бровь, а в глаз!
листаем до
\s \S
читаем:
\s - пробельный символ. Эквивалентно [\f\n\r\t\v].
думаем:
где тут написано, что пробел входит? что из этого [\f\n\r\t\v] пробел?
помечаем наличие косяка )))
Изменено: Ігор Гончаренко - 22.03.2021 11:22:41
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Ігор Гончаренко,  :D
там тест есть - я бы проверил сразу и тест показал что пробелы являются пробельными символами (но не неразрывный)
В любом случае, довольно неоднозначно для "справочника" - тут согласен, конечно
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Страницы: 1
Наверх