2017-04-17 105 views
4

我的VBA函數應該採用引用一系列單位的字符串(即"WAL1-5"),然後返回另一個字符串。正則表達式只返回1個匹配

我要帶的說法,並把它放在一個逗號分隔字符串, 所以"WAL1-5"應該成爲"WAL1, WAL2, WAL3, WAL4, WAL5".

它並不總是將是一個單一的數字。例如,我可能需要分開"DEV11-18"或類似的東西。

我從來沒有使用正則表達式,但不斷嘗試不同的東西,使這項工作,它似乎只能找到1場,而不是3

任何想法?這是我的代碼:

Private Function split_metergroup(ByVal group As String) As String 
    Dim re As Object 
    Dim matches As Object 
    Dim result As String 
    Dim prefix As String 
    Dim startVar As Integer 
    Dim endVar As Integer 
    Dim i As Integer 

    Set re = CreateObject("vbscript.regexp") 
    re.Pattern = "([A-Z]+)(\d+)[-](\d+)" 
    re.IgnoreCase = False 
    Set matches = re.Execute(group) 

    Debug.Print matches.Count 

    If matches.Count <> 0 Then 
     prefix = matches.Item(0) 
     startVar = CInt(matches.Item(1)) 'error occurs here 
     endVar = CInt(matches.Item(2)) 
     result = "" 

     For i = startVar To endVar - 1 
      result = result & prefix & i & "," 
     Next i 

     split_metergroup = result & prefix & endVar 
    Else 
     MsgBox "There is an error with splitting a meter group." 
     split_metergroup = "ERROR" 
    End If 

End Function 

我試着設置global = true,但我意識到這不是問題。該錯誤實際上發生在評論行上,但我認爲這是因爲只有1次匹配。

我試過Google搜索它,但每個人的情況似乎都與我的有點不同,因爲這是我第一次使用RE,我不認爲我理解模式足以查看是否可能是問題所在。

謝謝!

回答

2

@Shai瑞士雷達表的答覆工作。但是我自己想出了爲什麼我的原始代碼不工作,並且能夠輕鬆修改它。

該模式只發現1匹配,因爲它發現1滿匹配。完整匹配是整個字符串。 submatches真的是我想要得到的。看到下面的圖片,我實際得到的比賽。

Matches I was getting

而且這是我修改,使原來的代碼工作(要求爲1場全場比賽的每個子匹配):

How I modified the code

2

嘗試修改Function如下:

Private Function split_metergroup(ByVal group As String) As String 

    Dim re As Object 
    Dim matches As Variant 
    Dim result As String 
    Dim prefix As String 
    Dim startVar As Integer 
    Dim endVar As Integer 
    Dim i As Integer 

    Set re = CreateObject("VBScript.RegExp") 
    With re 
     .Global = True 
     .IgnoreCase = True 
     .Pattern = "[0-9]{1,20}" '<-- Modified the Pattern 
    End With 

    Set matches = re.Execute(group)     
    If matches.Count > 0 Then 
     startVar = CInt(matches.Item(0)) ' <-- modified 
     endVar = CInt(matches.Item(1)) ' <-- modified 
     prefix = Left(group, InStr(group, startVar) - 1) ' <-- modified 
     result = "" 

     For i = startVar To endVar - 1 
      result = result & prefix & i & "," 
     Next i  
     split_metergroup = result & prefix & endVar 
    Else 
     MsgBox "There is an error with splitting a meter group." 
     split_metergroup = "ERROR" 
    End If 

End Function 

Sub我已經測試過它:

Option Explicit 

Sub TestRegEx() 

Dim Res As String 

Res = split_metergroup("DEV11-18") 
Debug.Print Res 

End Sub 

結果我在即時窗口中有:

DEV11,DEV12,DEV13,DEV14,DEV15,DEV16,DEV17,DEV18 
+0

這工作!非常感謝你。:) 你知道原始圖案可能發生了什麼嗎?這並不重要,因爲我有工作代碼,但我只是好奇未來的參考。 –

+1

@TiannaProcon歡迎您,不要忘記標記爲「答案」 –

2

另一個正則表達式選項,這個使用SubMatches

測試

Sub TestRegEx() 
Dim StrTst As String 
MsgBox WallIndside("WAL7-21") 
End Sub 

代碼

Function WallIndside(StrIn As String) As String 

    Dim objRegex As Object 
    Dim objRegMC As Object 
    Dim lngCnt As Long 

    Set objRegex = CreateObject("VBScript.RegExp") 
    With objRegex 
     .Global = True 
     .IgnoreCase = True 
     .Pattern = "([a-z]+)(\d+)-(\d+)" 
     If .test(StrIn) Then 
      Set objRegMC = .Execute(StrIn) 
      For lngCnt = objRegMC(0).submatches(1) To objRegMC(0).submatches(2) 
       WallIndside = WallIndside & (objRegMC(0).submatches(0) & lngCnt & ", ") 
      Next 
       WallIndside = Left$(WallIndside, Len(WallIndside) - 2) 
     Else 
      WallIndside = "no match" 
     End If 
    End With 
End Function