繁体   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