Возвращение соответствия регулярному выражению в VBA (Excel) - PullRequest
43 голосов
/ 16 ноября 2011

Я пытаюсь написать функцию для 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, я получаю # ЗНАЧЕНИЕ!

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

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

Спасибо

1 Ответ

70 голосов
/ 16 ноября 2011

Вам необходимо получить доступ к матчам, чтобы получить номер 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-го параметра, если хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...