簡體   English   中英

VBA RegEx識別多種模式-Excel

[英]VBA RegEx identifiying multiple patterns - Excel

我是VBA RegEx的新手,但是由於這個stackoverflow線程

我明白了。 我有一個問題,希望有人可以提供幫助。 在Excel的第1行中,我有多個具有不同城市/國家/地區歸屬的字符串。 例:

A1: "/flights/munich/newyork"
A2: "flights/munich/usa"
A3:  "flights/usa/germany"
...

我現在想要的是一個VBA,該VBA通過RegEx遍歷這些字符串,並在滿足RegEx時提示分類值。 例:

A1: "/flights/munich/new-york" categorises as "city to city"
A2: "flights/munich/usa" categorises as "city to country"
A3:  "flights/usa/germany" categorises as "country to country"

現在,我有一個代碼可以將“城市到城市”類別返回給我,但是我無法弄清楚誰會得到處理多種模式並返回相應輸出字符串的代碼。

簡而言之,需要這樣的邏輯:

如果A1包含RegEx ".*/munich/new-york"則返回輸出字符串"city to city" ,如果A1包含RegEx ".*/munich/usa"則返回輸出字符串"city to country" ,依此類推。

猜猜這與如何處理VBA中具有多個模式的多個if語句有關,但是我無法弄清楚。

這就是我的代碼現在的樣子-希望您能提供幫助!

Function simpleCellRegex(Myrange As Range) As String
    Dim regEx As New RegExp
    Dim strPattern As String
    Dim strInput As String
    Dim strReplace As String
    Dim strOutput As String

    strPattern = "(munich|berlin|new-york|porto|copenhagen|moscow)/(munich|berlin|new-york|porto|copenhagen|moscow)"

    If strPattern <> "" Then
        strInput = Myrange.Value
        strReplace = "CITY TO CITY"

        With regEx
            .Global = True
            .MultiLine = True
            .IgnoreCase = False
            .Pattern = strPattern
        End With

        If regEx.Test(strInput) Then
            simpleCellRegex = regEx.Replace(strInput, strReplace)
        Else
            simpleCellRegex = "NO MATCH FOUND"
        End If
    End If

End Function

就像評論中提到的@dbmitch一樣,您不能使用單個Regex來完成此操作-您需要使用其中的3個。 我親自將城市和國家/地區納入Consts並根據需要構建模式。 然后,您可以將它們(以及strReplace )作為參數傳遞給simpleCellRegex函數:

Const CITIES As String = "(munich|berlin|new-york|porto|copenhagen|moscow)"
Const COUNTRIES As String = "(germany|france|usa|russia|etc)"

Function simpleCellRegex(Myrange As Range, strReplace As String, strPattern As String) As String
    Dim regEx As New RegExp
    Dim strPattern As String
    Dim strInput As String
    Dim strReplace As String
    Dim strOutput As String

    If strPattern <> "" Then
        strInput = Myrange.Value

        With regEx
            .Global = True
            .MultiLine = True
            .IgnoreCase = False
            .Pattern = strPattern
        End With

        If regEx.test(strInput) Then
            simpleCellRegex = regEx.Replace(strInput, strReplace)
        Else
            simpleCellRegex = "NO MATCH FOUND"
        End If
    End If
End Function

這樣稱呼:

foo = simpleCellRegex(someRange, "CITY TO CITY", CITIES & "/" & CITIES)
foo = simpleCellRegex(someRange, "CITY TO COUNTRY", CITIES & "/" & COUNTRIES)
foo = simpleCellRegex(someRange, "COUNTRY TO COUNTRY", COUNTRIES & "/" & COUNTRIES)

注意:如果您是在循環中執行此操作,則僅一次構建每個RegExp ,然后將作為參數而不是模式傳遞效率會大大提高。

一些(也許)“開箱即用”的解決方案:

Option Explicit

Sub main()
    Const CITIES As String = "MUNICH|BERLIN|NEWYORK|PORTO|COPENHAGEN|MOSCOW"
    Const COUNTRIES As String = "USA|GERMANY"

    With Worksheets("FLIGHTS")
        With .Range("A1", .Cells(.Rows.Count, 1).End(xlUp))
            With .Offset(, 1)
                .value = .Offset(, -1).value
                .Replace What:="*flights/", replacement:="", LookAt:=xlPart, MatchCase:=False
                .Replace What:="/", replacement:=" to ", LookAt:=xlPart, MatchCase:=False
                ReplaceElement .Cells, CITIES, "city"
                ReplaceElement .Cells, COUNTRIES, "country"
            End With
        End With
    End With
End Sub

Sub ReplaceElement(rng As Range, whats As String, replacement As String)
    Dim elem As Variant

    With rng
        For Each elem In Split(whats, "|")
            .Replace What:=elem, replacement:=replacement, LookAt:=xlPart, MatchCase:=False
        Next elem
    End With
End Sub

注意

  • 可以 replace()方法忽略大小寫,但要注意名稱之間的一致性:“ newyork”將永遠不會與“ new-york”匹配

我會做一些不同的事情。 我將正則表達式模式作為起點或終點,並將其與逗號分隔的一串城市或國家/地區匹配。

根據您的介紹,起點和終點將始終是最后兩個/分開的單位。

所以像這樣:

Option Explicit
Sub CategorizeFlights()
    Dim rData As Range, vData As Variant
    Dim arrCity() As Variant
    Dim arrCountry() As Variant
    Dim I As Long, J As Long
    Dim sCategoryStart As String, sCategoryEnd As String
    Dim V As Variant
    Dim RE As RegExp

arrCity = Array("munich", "newyork")
arrCountry = Array("usa", "germany")

Set RE = New RegExp
With RE
    .Global = False
    .ignorecase = True
End With

Set rData = Range("A2", Cells(Rows.Count, "A").End(xlUp)).Resize(columnsize:=2)
vData = rData

For I = 1 To UBound(vData, 1)
    V = Split(vData(I, 1), "/")

        RE.Pattern = "\b" & V(UBound(V) - 1) & "\b"
        If RE.test(Join(arrCity, ",")) = True Then
                sCategoryStart = "City to "
        ElseIf RE.test(Join(arrCountry, ",")) = True Then
                sCategoryStart = "Country to "
        Else
                sCategoryStart = "Unknown to "
        End If

        RE.Pattern = "\b" & V(UBound(V)) & "\b"
        If RE.test(Join(arrCity, ",")) = True Then
                sCategoryEnd = "City"
        ElseIf RE.test(Join(arrCountry, ",")) = True Then
                sCategoryEnd = "Country"
        Else
                sCategoryEnd = "Unknown"
        End If

    vData(I, 2) = sCategoryStart & sCategoryEnd
Next I

With rData
    .Value = vData
    .EntireColumn.AutoFit
End With

End Sub

在某些情況下,可以使用類似的算法而不使用正則表達式,但是我認為這是使用它的一種練習。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM