VBA – Universal RegEx Match Function

After yesterday’s post on how we can extract the MIME type from an HTML Img src attributes:

I thought that I’d show how we can slightly adapt the code to be universal.  Instead of creating one off functions for each and every scenario, how we can build a single function that we can use for all cases.
 

Extracting A Match Using RegEx

In the original code, to make it specific, we hard code the pattern which is only valid for that specific scenario.  So to make a more universal function, we need to make the pattern variable and supplied at runtime as a function input argument.

Then I got thinking, in some cases I need to retrieve the entire Match, yet in others I only was after the SubMatch, so I decided to make that another input argument as to what gets returned.

That all being said, here an example of a universal RegEx function which returns a single Match or SubMatch:

'---------------------------------------------------------------------------------------
' Procedure : RegEx_FindMatch
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Extract a RegEx's Match/SubMatch for a pattern, assuming a single match!
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
'             (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs: Early Binding -> Microsoft VBScript Regular Expressions X.X
'             Late Binding  -> None required
' References:
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sInput            : String to find a match in
' sPattern          : RegEx Pattern to use to find a match
' bReturnSubMatch   : Whether to return the entire match, or just a submatch, if applicable
'                       True  -> Return the SubMatch
'                       False -> Return the Match
'
' Output:
' ~~~~~~~
' Return either the Match or SubMatch (depending on bReturnSubMatch).  Returns "" if no
' Match/SubMatch is found.
'
' Usage:
' ~~~~~~
' ? RegEx_FindMatch("<img id=""sampleImg"" src=""data:image/png;base64,iVBORw0KGgo", "data:image\/(.*?);")
'   Returns -> data:image/png;
'
' ? RegEx_FindMatch("<img id=""sampleImg"" src=""data:image/png;base64,iVBORw0KGgo", "data:image\/(.*?);", True)
'   Returns -> png
'
' Revision History:
' Rev       Date(yyyy-mm-dd)        Description
' **************************************************************************************
' 1         2023-02-25              Initial Release
'---------------------------------------------------------------------------------------
Function RegEx_FindMatch(ByVal sInput As String, _
                         ByVal sPattern As String, _
                         Optional bReturnSubMatch As Boolean = False) As String
    On Error GoTo Error_Handler
    #Const RegEx_EarlyBind = False   'True => Early Binding / False => Late Binding
    #If RegEx_EarlyBind = True Then
        Dim oRegEx            As VBScript_RegExp_55.RegExp
        Dim oMatches          As VBScript_RegExp_55.MatchCollection
        
        Set oRegEx = New VBScript_RegExp_55.RegExp
    #Else
        Dim oRegEx            As Object
        Dim oMatches          As Object
        
        Set oRegEx = CreateObject("VBScript.RegExp")
    #End If

    With oRegEx
        .Pattern = sPattern
        .Global = True
        .IgnoreCase = True
        .MultiLine = True
        Set oMatches = .Execute(sInput)
    End With
    If oMatches.Count <> 0 Then
        If bReturnSubMatch Then
            If oMatches(0).SubMatches.Count <> 0 Then
                RegEx_FindMatch = oMatches(0).SubMatches(0)
            End If
        Else
            RegEx_FindMatch = oMatches(0)
        End If
    End If

Error_Handler_Exit:
    On Error Resume Next
    Set oMatches = Nothing
    Set oRegEx = Nothing
    Exit Function

Error_Handler:
    MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: RegEx_FindMatch" & vbCrLf & _
           "Error Description: " & Err.Description & _
           Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
           , vbOKOnly + vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Function

 

Usage Examples

Example 1 – Extracting the MIME Type From An HTML Img Tag Src Attribute

We can use it to perform the same action as in the previous article by simply doing:

? RegEx_FindMatch("<img id=""sampleImg"" src=""data:image/png;base64,iVBORw0KGgo", "data:image\/(.*?);")

which returns the Match

data:image/png;

Or

? RegEx_FindMatch("<img id=""sampleImg"" src=""data:image/png;base64,iVBORw0KGgo", "data:image\/(.*?);", True)

which returns the SubMatch

png

Example 2 – Extracting the Element Id From An HTML Img Tag

Now say we wanted to instead extract the id from that same string, we could simply do:

? RegEx_FindMatch("<img id=""sampleImg"" src=""data:image/png;base64,iVBORw0KGgo", "id=[""'](.*?)[""']")

which returns the Match

id="sampleImg"

Or

? RegEx_FindMatch("<img id=""sampleImg"" src=""data:image/png;base64,iVBORw0KGgo", "id=[""'](.*?)[""']", True)

which returns the SubMatch

sampleImg

Example 3 – Extracting A Phone Number From A String

We could similarily use it to extract a phone number from a string by doing:

? RegEx_FindMatch("I have some random text 613-772-1903 with a phone number in it.", "([0-9]{3}-[0-9]{3}-[0-9]{4})")

which returns the Match

613-772-1903

So on and so forth.

As long as you create a pattern that works, then you no longer need to create separate functions, just use this one!

So by simply supplying the Pattern, we can use the same function for any usage scenario when there will be only a single Match or SubMatch.