[英]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
注意
我會做一些不同的事情。 我將正則表達式模式作為起點或終點,並將其與逗號分隔的一串城市或國家/地區匹配。
根據您的介紹,起點和終點將始終是最后兩個/
分開的單位。
所以像這樣:
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.