Check for Numeric Value in Word Macro using Regular Expressions - regex

Is it possible to directly use regular expressions in Word macros?
I want to check if a string contains only numbers and the following code does not work.
isNumber = RegEx.IsMatch("234", "[0-9]+$")
I simply need it to return true or false.

You can create an instance of the VBScript.Regexp object within your code, but an easier solution would be to use the existing VBA function IsNumeric. Both methods are included below:
Sub testNumeric()
'Use IsNumeric
MsgBox (IsNumeric("12345")) 'Returns true
MsgBox (IsNumeric("123a")) 'Returns false
'Alternatively, using Regexp Object
Dim regexp
Set regexp = CreateObject("VBScript.Regexp")
regexp.Pattern = "[0-9]+$"
MsgBox (regexp.test("12345")) 'Returns true
MsgBox (regexp.test("123a")) 'Returns false
End Sub
Note that the regex pattern does not strictly return numbers, but also any string that ends with numbers (i.e. testing "a123" returns true). To make the regex check strictly numeric, the pattern could be ^[0-9]+$. Thanks to #mike for pointing this out.

Related

VBA regexp pattern combining match and not matching a pattern

Trying to extract valid phone numbers from a string with no visible delimiters between different data types. In effect, the data around the potential phone number is random and irrelevant.
What should be matched. I am trying to match either one of the following:
[random garbage][optional '1'][optional '(']###[optional')'[[random or no white space]###-####[random garbage] or
[random garbage]###[optional '-']###,[optional '-']####[random garbage]
Only the 1st phone number is to be used, so I used Global = False in the code below. I could make it even more robust, but I've examined the data and this should be enough.
Working pattern.Here's a code snippet from a function (it returns the matching phone number) that contains the pattern that worked.
With regex
.Global = False
.Pattern = "1?(\(?\d{3}\)?\(s+)?|\d{3}-?)\d{3}-?\d{4}"
'this works but does detect an extension as explained above
End With
What should not be matched. I realized that I also need to search for an extension next to the phone number (i.e. [phone number][white space]x#) and if that exists, to treat the phone number as invalid (.test should evaluate to false).
Failed attemps. They all failed (even valid phone numbers had .test evaluate to false):
.Pattern = "1?(\(?\d{3}\)?\(s+)?|\d{3}-?)\d{3}-?\d{4}^(\s?x\d)"
'detect not([optional single white space]x#), added "^(\s?x\d)"
'or
.Pattern = "1?(\(?\d{3}\)?\(s+)?|\d{3}-?)\d{3}-?\d{4}^((\s+?)[x]\d)"
'detect not([optional multiple white space]x#), added "^((\s+?)[x]\d)"
Not sure how to combine positive match tests and negative (not) match tests in the same pattern.
Work-arounds I've tried. When I couldn't get it to work, I tried the following Like patterns (using VBA 'Like', prior to calling the function that utilized Regexp) and that also failed (all evaluated to false even with test strings that contained examples such as "...1x2" or "5 x33" or "...7 x444"; with patterns like "*#x#*", "*#{ x}#*", ""*#{ x}#*".
Here is the code snippet to test the Like function:
If Not (OrigNum Like "*#x#" Or OrigNum Like "*#[ x}#" Or OrigNum Like "*#[ x]#*") Then
Debug.Print "No #x# in string"
OrigNum = ExtractPhoneNumber(OrigNum)
Else
Debug.Print "#x# in string"
End If
Every string evaluated ended up causing "No x# in string" to be displayed (evaluated to false), even when the string contained the above examples, which should have evaluated to true and "#x# in string" being displayed.
Dazed and confused for so long it's...OK, enough of the Led Zepp reference :-)
Phone number:
[optional '1'][optional '(']###[optional')'[[random or no white space]###-####
###[optional '-']###[optional '-']####
*I removed a comma I assumed as a typo, and also assuming the leading 1 is optional for both cases from what I read from your patterns.
Don't match:
[phone number][white space]x#
What you're looking for is negative lookaheads.
(?! subexpression ) asserts for that subexpression from the current position and, if the subexpression matches, the match attempt fails (i.e. not followed by).
E.g. (?!\s*x\d) fails when the current position is followed by optional whitespace, an "x" and a digit.
Regex:
1?(?:\(\d{3}\)|\d{3}-?)\s*\d{3}-?\d{4}(?!\s*x\d)
Code:
Public Function getPhoneNumber(strInput As String) As Variant
Dim regex As New RegExp
Dim matches As Object
regex.Pattern = "1?(?:\(\d{3}\)\s*|\d{3}-?)\d{3}-?\d{4}(?!\s*x\d)"
regex.Global = False
Set matches = regex.Execute(strInput)
If matches.Count = 0 Then
getPhoneNumber = CVErr(xlErrNA)
Else
getPhoneNumber = matches(0).Value
End If
End Function
Results (🎵As it was, then again it will be; though the course may change sometimes🎵):

VB6 Like operator not picking up space character

I have a legacy app whereby email addresses are validated using a RegEx experssion passed to VB6 and then compared using the Like operator
The RegEx expression is still allowing space characters to be included in the email address which I do not want.
The code below - I want the first to retru True but the second to return False. What amendment to I need to make to the RegEx expression?
Sub LikeTest()
MsgBox "hello#hello.com" Like "[A-Za-z0-9-\.\]*#*[A-Za-z0-9-\.\].*[A-Za-z]" 'returns True
MsgBox "hello# hello.com" Like "[A-Za-z0-9-\.\]*#*[A-Za-z0-9-\.\].*[A-Za-z]" 'returns True but should return False
End Sub
DIM test
test = LikeTest("hello#hello.com")
Function LikeTest(sEmail)
RegExpTest = false
Dim regEx, retVal
Set regEx = New RegExp
' Create regular expression:
regEx.Pattern ="^[\w-\.]{1,}\#([\da-zA-Z-]{1,}\.){1,}[\da-zA-Z-]{2,3}$"
' Set pattern:
regEx.IgnoreCase = true
' Set case sensitivity.
retVal = regEx.Test(sEmail)
' Execute the search test.
If not retVal Then
RegExpTest = false
else
RegExpTest = true
End If
MsgBox(RegExpTest)
End Function
Source:
https://web.archive.org/web/20061026092253/http://www.4guysfromrolla.com/aspfaqs/ShowFAQ.asp?FAQID=47

Find specific instance of a match in string using RegEx

I am very new to RegEx and I can't seem to find what I looking for. I have a string such as:
[cmdSubmitToDatacenter_Click] in module [Form_frm_bk_UnsubmittedWires]
and I want to get everything within the first set of brackets as well as the second set of brackets. If there is a way that I can do this with one pattern so that I can just loop through the matches, that would be great. If not, thats fine. I just need to be able to get the different sections of text separately. So far, the following is all I have come up with, but it just returns the whole string minus the first opening bracket and the last closing bracket:
[\[-\]]
(Note: I'm using the replace function, so this might be the reverse of what you are expecting.)
In my research, I have discovered that there are different RegEx engines. I'm not sure the name of the one that I'm using, but I'm using it in MS Access.
If you're using Access, you can use the VBScript Regular Expressions Library to do this. For example:
Const SOME_TEXT = "[cmdSubmitToDatacenter_Click] in module [Form_frm_bk_UnsubmittedWires]"
Dim re
Set re = CreateObject("VBScript.RegExp")
re.Global = True
re.Pattern = "\[([^\]]+)\]"
Dim m As Object
For Each m In re.Execute(SOME_TEXT)
Debug.Print m.Submatches(0)
Next
Output:
cmdSubmitToDatacenter_Click
Form_frm_bk_UnsubmittedWires
Here is what I ended up using as it made it easier to get the individual values returned. I set a reference to the Microsoft VBScript Regular Expression 5.5 so that I could get Intellisense help.
Public Sub GetText(strInput As String)
Dim regex As RegExp
Dim colMatches As MatchCollection
Dim strModule As String
Dim strProcedure As String
Set regex = New RegExp
With regex
.Global = True
.Pattern = "\[([^\]]+)\]"
End With
Set colMatches = regex.Execute(strInput)
With colMatches
strProcedure = .Item(0).submatches.Item(0)
strModule = .Item(1).submatches.Item(0)
End With
Debug.Print "Module: " & strModule
Debug.Print "Procedure: " & strProcedure
Set regex = Nothing
End Sub

using classic asp for regular expression

We have some Classic asp sites, and i'm working on them a lil' bit, and I was wondering how can I write a regular expression check, and extract the matched expression:
the expression I have is in the script's name
so Let's say this
Response.Write Request.ServerVariables("SCRIPT_NAME")
Prints out:
review_blabla.asp
review_foo.asp
review_bar.asp
How can I get the blabla, foo and bar from there?
Thanks.
Whilst Yots' answer is almost certainly correct, you can achieve the result you are looking for with a lot less code and somewhat more clearly:
'A handy function i keep lying around for RegEx matches'
Function RegExResults(strTarget, strPattern)
Set regEx = New RegExp
regEx.Pattern = strPattern
regEx.Global = true
Set RegExResults = regEx.Execute(strTarget)
Set regEx = Nothing
End Function
'Pass the original string and pattern into the function and get a collection object back'
Set arrResults = RegExResults(Request.ServerVariables("SCRIPT_NAME"), "review_(.*?)\.asp")
'In your pattern the answer is the first group, so all you need is'
For each result in arrResults
Response.Write(result.Submatches(0))
Next
Set arrResults = Nothing
Additionally, I have yet to find a better RegEx playground than Regexr, it's brilliant for trying out your regex patterns before diving into code.
You have to use the Submatches Collection from the Match Object to get your data out of the review_(.*?)\.asp Pattern
Function getScriptNamePart(scriptname)
dim RegEx : Set RegEx = New RegExp
dim result : result = ""
With RegEx
.Pattern = "review_(.*?)\.asp"
.IgnoreCase = True
.Global = True
End With
Dim Match, Submatch
dim Matches : Set Matches = RegEx.Execute(scriptname)
dim SubMatches
For Each Match in Matches
For Each Submatch in Match.SubMatches
result = Submatch
Exit For
Next
Exit For
Next
Set Matches = Nothing
Set SubMatches = Nothing
Set Match = Nothing
Set RegEx = Nothing
getScriptNamePart = result
End Function
You can do
review_(.*?)\.asp
See it here on Regexr
You will then find your result in capture group 1.
You can use RegExp object to do so.
Your code gonna be like this:
Set RegularExpressionObject = New RegExp
RegularExpressionObject.Pattern = "review_(.*)\.asp"
matches = RegularExpressionObject.Execute("review_blabla.asp")
Sorry, I can't test code below right now.
Check out usage at MSDN http://msdn.microsoft.com/en-us/library/ms974570.aspx

VBA Regex issue

has VBA any good mechanism for checking, if the content of a given Excel Cell matches a specific regex?
In my case i want to know, if some cell has the format
m
m2
m1234
In fact, there's just one defined letter at the beginning, followed by a not specified amount of numbers.
How do I put this into an If-Else construct?
If Doc.Cells(1,1).Value ..... ???
greets, poeschlorn
You can get at the VBScript RegExp objects via Tools->References & adding "Microsoft VBScript Regular Expressions 5.5"
Alternatively a quick way to do it, if you don't need to check for a subsequent letter as in `m1234X1 is:
if Doc.Cells(1,1).Value like "[a-zA-Z]#*" then ...
(This doesn't require a reference to anything)
I don't know VBA, but the regex [a-zA-Z][0-9]* might be able to match what you want.
Here is my RegexContains function. Pass it the cell and the pattern and it will return TRUE or FALSE if it contains it or not.
Function RegexContains(ByVal find_in As String, _
ByVal find_what As String, _
Optional IgnoreCase As Boolean = False) As Boolean
Application.ScreenUpdating = False
Dim RE As Object
Set RE = CreateObject("vbscript.regexp")
RE.Pattern = find_what
RE.IgnoreCase = IgnoreCase
RE.Global = True
RegexContains = RE.Test(find_in)
Application.ScreenUpdating = True
End Function
Now, I'm not sure exactly what you want to find in your example, but if you want to know if the cell contains a single letter followed by one or more letters, then you would use (assuming the cell is A1): =RegexContains(A1, "^\w\d+")
The ^ marks the start of the sentence
The \w marks a single alphabetic
character (a-zA-Z)
The \d+ marks one or more numeric
characters[0-9]
I hope this helps.