2017-04-17 113 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