Search code examples
regexvbams-wordvbscript

How to get the position of submatches in VBA?


I need to get the index position value of submatched string. As per documentation, I have read through this Regular expression and got to know FirstIndex property to get the position of matched string.

But this works only for one dimensional matched string. I couldn't apply FirstIndex for submatches. Pls refer sample matches

I tried this format,

        Dim myRegExp As Object, match As MatchCollection            
        Dim matched As String
        Set myRegExp = CreateObject("VBScript.RegExp")
        myRegExp.pattern = find
        If myRegExp.test(text) = True Then
        Set match = myRegExp.Execute(text)          
        Debug.Print match(0).submatches(0) '' this is matched string

Where should I call FirstIndex to get position of submatched string

output:

match(0)=>Berry, Brent. (2006). What accounts for race and ethnic differences in  Berry, 
Brent. parental financial transfers to adult children in the United States? Journal of Family
Issues 37:1583-1604.   

submatches(0)=>Berry, Brent.
submatches(6)=>2006

EXPECTED OUTPUT:

submatches(0) at 0th position
submatches(6) at 16th position and so on

Solution

  • You can't apply .FirstIndex to SubMatches(x) because it returns a String, not a Match. If the groups will return unique matches, you can find its location by simply using the Instr function:

    With CreateObject("VBScript.RegExp")
        .Pattern = Find
        If .Test(text) Then
            Set match = .Execute(text)
            Debug.Print InStr(1, text, match(0).SubMatches(0)) '0
            Debug.Print InStr(1, text, match(0).SubMatches(5)) '16
            'and so on
        End If
    End With
    

    If the groups will not return unique results, you can track the position of the last match and loop through the results. Note that VBScript.RegExp doesn't support look-behinds, so you don't have to take the length of the matches into account:

    With CreateObject("VBScript.RegExp")
        .Pattern = find
        If .Test(text) Then
            Set match = .Execute(text)
            Dim i As Long, pos As Long, found As String
            pos = 1
            For i = 0 To match(0).SubMatches.Count - 1
                found = match(0).SubMatches(i)
                pos = InStr(pos, text, match(0).SubMatches(i)) 
                Debug.Print found, pos
            Next
        End If
    End With