[英]VBA RegEx identifiying multiple patterns - Excel
I´m rather new to VBA RegEx, but thanks to this stackoverflow thread , 我是VBA RegEx的新手,但是由于这个stackoverflow线程 ,
I am getting to it. 我明白了。 I have a problem and hope that somebody can help. 我有一个问题,希望有人可以提供帮助。 In row 1 in Excel I have multiple Strings with different city/country attribution. 在Excel的第1行中,我有多个具有不同城市/国家/地区归属的字符串。 Example: 例:
A1: "/flights/munich/newyork"
A2: "flights/munich/usa"
A3: "flights/usa/germany"
...
What I wanna have now, is a VBA that goes though those strings with RegEx and prompts a categorisation value if the RegEx is met. 我现在想要的是一个VBA,该VBA通过RegEx遍历这些字符串,并在满足RegEx时提示分类值。 Example: 例:
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"
Right now, I have a code that will return the "city to city" category to me, but I can´t figure out who to get a code that handles the multiple patterns and returns the corresponding output string. 现在,我有一个代码可以将“城市到城市”类别返回给我,但是我无法弄清楚谁会得到处理多种模式并返回相应输出字符串的代码。
In short, a logic like this is needed: 简而言之,需要这样的逻辑:
If A1 contains RegEx ".*/munich/new-york"
then return output string "city to city"
, if A1 contains RegEx ".*/munich/usa"
then return output string "city to country"
and so on. 如果A1包含RegEx ".*/munich/new-york"
则返回输出字符串"city to city"
,如果A1包含RegEx ".*/munich/usa"
则返回输出字符串"city to country"
,依此类推。
Guess this has something to to with how to handle multiple if statements with multiple patterns in VBA, but I can´t figure it out. 猜猜这与如何处理VBA中具有多个模式的多个if语句有关,但是我无法弄清楚。
This is how my code looks right now - hope you can help! 这就是我的代码现在的样子-希望您能提供帮助!
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
Like @dbmitch mentions in the comments, you can't do this with a single Regex - you'll need to use 3 of them. 就像评论中提到的@dbmitch一样,您不能使用单个Regex来完成此操作-您需要使用其中的3个。 I'd personally put the cities and countries into Consts
and build the patterns as need. 我亲自将城市和国家/地区纳入Consts
并根据需要构建模式。 You can then pass them (along with the strReplace
) as parameters to simpleCellRegex
function: 然后,您可以将它们(以及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
Called like this: 这样称呼:
foo = simpleCellRegex(someRange, "CITY TO CITY", CITIES & "/" & CITIES)
foo = simpleCellRegex(someRange, "CITY TO COUNTRY", CITIES & "/" & COUNTRIES)
foo = simpleCellRegex(someRange, "COUNTRY TO COUNTRY", COUNTRIES & "/" & COUNTRIES)
Note: If you're doing this in a loop, it would be wildly more efficient to only build each RegExp
once , and then pass that as a parameter instead of the pattern. 注意:如果您是在循环中执行此操作,则仅一次构建每个RegExp
,然后将其作为参数而不是模式传递,效率会大大提高。
A little (maybe) "out of the box" solution: 一些(也许)“开箱即用”的解决方案:
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
note 注意
I would do this a bit differently. 我会做一些不同的事情。 I would make the regex pattern the start or end point, and match it against a comma delimited string of cities or countries. 我将正则表达式模式作为起点或终点,并将其与逗号分隔的一串城市或国家/地区匹配。
Given what you have presented, the start and end points will always be the last two /
separated units. 根据您的介绍,起点和终点将始终是最后两个/
分开的单位。
So something like: 所以像这样:
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
As is sometimes the case, a similar algorithm can be used without regular expressions, but I assume this is an exercise in its use. 在某些情况下,可以使用类似的算法而不使用正则表达式,但是我认为这是使用它的一种练习。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.