Возвращение соответствия регулярному выражению в VBA (Excel)

37

Я пытаюсь написать функцию для excel 2010, которая возьмет ячейку неструктурированного текста, ищите что-то, называемое значением sdi, и, если найдено, верните это число. Значение sdi будет отображаться как sdi ####. То, что я хочу, это вернуть sdi и выделенные для него номера, поэтому, если ячейка содержит "некоторый текст sdi 1234 еще текст", функция вернет sdi 1234.

Это моя функция:

Function SdiTest(LookIn As String) As String
  Dim temp As String
  Dim STA As Object
  temp = ""

  Set SDI = CreateObject("VBScript.RegExp")
  SDI.IgnoreCase = True
  SDI.Pattern = "sdi [1-9]*"
  SDI.Global = True

  If SDI.Test(LookIn) Then
    temp = SDI.Execute(LookIn)
  End If

  SdiTest = temp
End Function

Если нет номера sdi, он никогда не входит в оператор if и добросовестно возвращает пустую строку. Если есть номер sdi, я получаю #VALUE!

Что мне не хватает?

Да, VBScript включен. Кроме того, мне кажется неудобным использовать регулярное выражение в VBA и сложно найти полезную информацию в Интернете. Ссылки на хорошие онлайн-ресурсы будут оценены.

Спасибо

Теги:
excel

1 ответ

57
Лучший ответ

Вам нужно получить доступ к совпадениям, чтобы получить номер SDI. Вот функция, которая сделает это (при условии, что на ячейку всего 1 номер SDI).

Для регулярного выражения я использовал "sdi, за которым следует пробел и одно или несколько чисел". У вас было "sdi, а затем пробел и ноль или более чисел". Вы можете просто изменить + на * в моем шаблоне, чтобы вернуться к тому, что у вас было.

Function ExtractSDI(ByVal text As String) As String

Dim result As String
Dim allMatches As Object
Dim RE As Object
Set RE = CreateObject("vbscript.regexp")

RE.pattern = "(sdi \d+)"
RE.Global = True
RE.IgnoreCase = True
Set allMatches = RE.Execute(text)

If allMatches.count <> 0 Then
    result = allMatches.Item(0).submatches.Item(0)
End If

ExtractSDI = result

End Function

Если ячейка может содержать более одного номера SDI, который вы хотите извлечь, вот моя функция RegexExtract. Вы можете передать третий параметр для разделения каждого матча (например, разделять запятыми), и вы вручную вводите шаблон в фактический вызов функции:

Ex) =RegexExtract(A1, "(sdi \d+)", ", ")

Вот:

Function RegexExtract(ByVal text As String, _
                      ByVal extract_what As String, _
                      Optional seperator As String = "") As String

Dim i As Long, j As Long
Dim result As String
Dim allMatches As Object
Dim RE As Object
Set RE = CreateObject("vbscript.regexp")

RE.pattern = extract_what
RE.Global = True
Set allMatches = RE.Execute(text)

For i = 0 To allMatches.count - 1
    For j = 0 To allMatches.Item(i).submatches.count - 1
        result = result & seperator & allMatches.Item(i).submatches.Item(j)
    Next
Next

If Len(result) <> 0 Then
    result = Right(result, Len(result) - Len(seperator))
End If

RegexExtract = result

End Function

* Обратите внимание, что я взял "RE.IgnoreCase = True" из моего RegexExtract, но вы можете добавить его обратно или даже добавить в качестве необязательного 4-го параметра, если хотите.

  • 0
    Отличный ответ, спасибо за функцию!
  • 0
    Спасибо Issun - ваша функция работает чудесно
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню