VB6 Like operator not picking up space character - regex

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

Related

Regular Expression to return false if anything in the string is other than exactly what the pattern checks for

I'm trying to make a pattern that will return false if there's ANYTHING in the string other than exactly what the pattern checks for.
I believe that this is supposed to be achieved by putting the entire pattern between a "^" and a "$".
Sub Macro1()
Dim cellValue As String
cellValue = "7:11 AM NBR Unavail"
Dim callPattern As String
callPattern = "^[1]{0,1}[1-9][:][0-9]{2}[ ]AM|PM$"
Dim regEx As New RegExp
With regEx
.IgnoreCase = False
.Pattern = callPattern
End With
If regEx.Test(cellValue) Then
MsgBox ("Got it!")
Else
MsgBox ("Don't got it...")
End If
End Sub
The variable cellValue has text after the AM|PM that the pattern checks for, yet when I run it I still get the "Got it!" message.
I experimented with the following string and pattern earlier and the "$" at the end worked as intended. Why isn't it working with the above code?
cellValue = "7:11 PM (555) 444-3333"
callPattern = "^[1]{0,1}[1-9][:][0-9]{2}[ ]AM|PM[ ][(][0-9]{3}[)][ ][0-9]{3}[-][0-9]{4}$"
I think you have to enclose parenthesis between AM|PM as following.
callPattern = "^[1]{0,1}[1-9][:][0-9]{2}[ ](AM|PM)$"
Your pattern means
"^[1]{0,1}[1-9][:][0-9]{2}[ ]AM" or "PM$"
also second pattern means
"^[1]{0,1}[1-9][:][0-9]{2}[ ]AM" or "PM[ ][(][0-9]{3}[)][ ][0-9]{3}[-][0-9]{4}$"
You can reduce the pattern down to this:
^1?[1-9]:\d{2} (AM|PM) \(\d{3}\) \d{3}-\d{4}$
Test it here

Replace matched pattern with different font

I am using Outlook 2010, and I am trying to write a macro to replace the font of text with a different one, if it matches a pattern.
The logic I am trying to apply is simple - in the user selected text, check for a pattern, and on match, change the font for the matched text.
So far I have been able to split the text and apply/check regex, but the replacement is something that I am not clear on how to do.
Dim objOL As Application
Dim objDoc As Object
Dim objSel As Object
Dim regEx As RegExp
Dim matches As MatchCollection
Dim m As Match
Dim lines As Variant
Dim ms As String
Set objOL = Application
Set objDoc = objOL.ActiveInspector.WordEditor
Set objSel = objDoc.Windows(1).Selection
lines = Split(objSel, Chr(13))
For i = 0 To UBound(lines) Step 1
Set regEx = New RegExp
With regEx
.Pattern = "\[(ok|edit|error)\](\[.*\])?" ' <-- this is just one regex, I want to be able to check more regexes
.Global = True
End With
If regEx.Test(lines(i)) Then
Set matches = regEx.Execute(lines(i))
For Each m In matches
ms = m.SubMatches(1)
' ms.Font.Italic = True
' <-- here is where I am not sure how to replace! :( -->
Next
End If
Next i
P.S there seems to be text-search (objSel.Find.Text)and replace (objSel.Find.Replacement.Text) methods in Selection object, but not pattern-search ! (or I am missing it)
--EDIT--
Adding a sample text
user#host> show some data
..<few lines of data>.. <-- these lines as-is (but monospaced)
[ok][2014-11-26 11:05:02]
user#host> edit some other data
[edit data]
user#host(data)% some other command
I want to convert the whole block to a monospaced font (like Courier New, or Consolas)
And change the part that begins with something#somewhere.. and till > or % to dimmer color,
(i.e in this example user#host> and user#host(data)% dimmer/grey)
The rest in that line to bold (show some data et al)
And, all the bracketed text followed by time-stamps (or without timestamps) similar to 2. (i.e, dim/grey)
This is getting closer to being done. The framework is here to make all sorts of changes now. Just need to get some of the regex patterns down to make the changes.
Sub FormatSelection()
Dim objMailItem As Outlook.MailItem
Dim objInspector As Outlook.Inspector: Set objInspector = Application.ActiveInspector
Dim objHtmlEditor As Object
Dim objWord As Object
Dim Range As Word.Selection
Dim objSavedSelection As Word.Selection
Dim objFoundText As Object
' Verify a mail object is in focus.
If objInspector.CurrentItem.Class = olMail Then
' Get the mail object.
Set objMailItem = objInspector.CurrentItem
If objInspector.EditorType = olEditorWord Then
' We are using a Word editor. Get the selected text.
Set objHtmlEditor = objMailItem.GetInspector.WordEditor
Set objWord = objHtmlEditor.Application
Set Range = objWord.Selection
Debug.Print Range.Range
' Set defaults for the selection
With Range.Font
.Name = "Courier"
.ColorIndex = wdAuto
End With
' Stylize the bracketed text
Call FormatTextWithRegex(Range, 2, "\[(.+?)\]")
' Prompt style text.
Call FormatTextWithRegex(Range, 2, "(\w+?#.+?)(?=[\>\%])")
' Text following the prompt.
Call FormatTextWithRegex(Range, 3, "(\w+?#.+?[\>\%])(.+)")
End If
End If
Set objInspector = Nothing
Set Range = Nothing
Set objHtmlEditor = Nothing
Set objMailItem = Nothing
End Sub
Private Sub FormatTextWithRegex(ByRef pRange As Word.Selection, pActionIndex As Integer, pPattern As String)
' This routine will perform a regex replacement on the text in pRange using pPattern
' on text based on the pactionindex passed.
Const intLightColourIndex = 15
Dim objRegex As RegExp: Set objRegex = New RegExp
Dim objSingleMatch As Object
Dim objMatches As Object
' Configure Regex object.
With objRegex
.IgnoreCase = True
.MultiLine = False
.Pattern = pPattern ' Example "\[(ok|edit|error)\](\[.+?\])?"
.Global = True
End With
' Locate all matches if any.
Set objMatches = objRegex.Execute(pRange.Text)
' Find
If (objMatches.Count > 0) Then
Debug.Print objMatches.Count & " Match(es) Found"
For Each objSingleMatch In objMatches
' Locate the text associated to this match in the selection so we can replace it.
Debug.Print "Match Found: '" & objSingleMatch & "'"
With pRange.Find
'.ClearFormatting
.Text = objSingleMatch.Value
.ClearFormatting
Select Case pActionIndex
Case 1 ' Italisize text
.Replacement.Text = objSingleMatch.Value
.Replacement.Font.Bold = False
.Replacement.Font.Italic = True
.Replacement.Font.ColorIndex = wdAuto
.Execute Replace:=wdReplaceAll
Case 2 ' Dim the colour
.Replacement.Text = objSingleMatch.Value
.Replacement.Font.Bold = False
.Replacement.Font.Italic = False
.Replacement.Font.ColorIndex = intLightColourIndex
.Execute Replace:=wdReplaceAll
Case 3 ' Bold that text!
.Replacement.Text = objSingleMatch.Value
.Replacement.Font.Bold = True
.Replacement.Font.Italic = False
.Replacement.Font.ColorIndex = wdAuto
.Execute Replace:=wdReplaceAll
End Select
End With
Next
Else
Debug.Print "No matches found for pattern: " & pPattern
End If
Set objRegex = Nothing
Set objSingleMatch = Nothing
Set objMatches = Nothing
End Sub
So we take what the user has selected and execute the macro. I have my Outlook configured with Word for the editor so that is tested for. Take the selected text and run the regex query against the text saving the matches.
The issue you had is what to do with the match once you found it. In my case since we have the actual text that matched we can run that through a find and replace using the selection once again. Replacing the text with itself instead styled as directed.
Caveats
My testing text was the following:
asdfadsfadsf [ok][Test]dsfadsfasdf asdfadsfadsfasdfasdfadsfadsf [ok][Test]dsfadsfasdf asdfadsfadsfasdf
I had to change your regex in your sample to be less greedy since it was matching both [ok][Test] sections. I don't know what kind of text you are working with so my logic might not apply to your situation. Test with caution.
You also had a comment that you needed to test multiple regexes... regexies.... I don't know what the plural is. Wouldn't be hard to create another function that calls this one for several patterns. Assuming this logic works repeating it should not be a big deal. I would like to make this work for you so if something is wrong let me know.
Code Update
I have changed the code so that the regex replacement is in a sub. So what the code does right now is change the selected text to courier and italisize text based on a regex. Now with how it is set up you can use the sub routine FormatTextWithRegex to make changes. Just need to update the pattern and action index which will perform the different styles. Will be updating this again soon with more information. Right now all that exists is the structure that I think you need.
Having issues with the bolding still but you can see the grey part is working correctly. Also the since this relies on highlighting the multiple calls to the function are causing an issue. Just not sure what it is.

Check for Numeric Value in Word Macro using Regular Expressions

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.

Regex using Interval Matching (Exact or Range)

I'm trying to use the regex feature of Ms Access 2007 VBA but I'm doing something wrong.
If I have a regex of:
\$\d{3,5}\.\d{2}
The following gives me a True: $123.45
And these give me False: $12.23 or $123456.45
So all is good with this.
However, if I now test this, it gives me True !?
$123.456
Isn't the second section of my regex, ie \d{2} stating that I can only have two digits after the decimal/period?
This problem also occurs even if I put a boundary, ie \d{2,2}
Sorry; figured it out. I used the boundaries functionality.
Therefore the following now works:
\$\d{3,5}\.\b\d{2}\b
If there are any other thoughts or suggestions I'd still be more than grateful
' you confirmed you don't want this ...
? RegExpTest("$123.456", "\$\d{3,5}\.\d{2}")
True
' you can add "$" to the regex pattern ...
? RegExpTest("$123.456", "\$\d{3,5}\.\d{2}$")
False
Function RegExpTest(ByVal pSource As String, _
ByVal pPattern As String) As Boolean
Dim re As Object ' New RegExp
Set re = CreateObject("VBScript.RegExp")
With re
.Pattern = pPattern
.IgnoreCase = True
.Global = False
.MultiLine = False
End With
RegExpTest = re.Test(pSource)
Set re = Nothing
End Function

Regular Expressions in VbScript?

Does VbScript have a native implementation for Regex? I need to validate e-mail addresses on an old ASP application.
Any pointers would be great.
Since the top answer here is in VB6 I thought I'd add one here in VBScript (since that's what the question is asking for):-
Option Explicit
Function GetEmailValidator()
Set GetEmailValidator = New RegExp
GetEmailValidator.Pattern = "^((?:[A-Z0-9_%+-]+\.?)+)#((?:[A-Z0-9-]+\.)+[A-Z]{2,4})$"
GetEmailValidator.IgnoreCase = True
End Function
Dim EmailValidator : Set EmailValidator = GetEmailValidator()
Now some tests:-
Response.Write EmailValidator.Test("") = False
Response.Write EmailValidator.Test(" ") = False
Response.Write EmailValidator.Test("somebody#domain.co.uk") = True
Response.Write EmailValidator.Test("someone#domain.com") = True
Response.Write EmailValidator.Test("some.body#domain.co.uk") = True
Response.Write EmailValidator.Test("broken#domain..co.uk") = False
Response.Write EmailValidator.Test("#oops.co.uk") = False
Response.Write EmailValidator.Test("name") = False
Response.Write EmailValidator.Test("name#uk") = False
Response.Write EmailValidator.Test("name#uk") = False
Response.Write EmailValidator.Test("name#domain.abcde") = False
This example is by AlexCuse from LessThanDot
Function ValidEmail(ByVal emailAddress)
'this function will use regular expressions to check an '
'email address for validity '
'instantiate regex object container, output boolean '
Dim objRegEx, retVal
'using late binding, vbscript reference is not required '
Set objRegEx = CreateObject("VBScript.RegExp")
'.pattern -looks for a valid email address '
With objRegEx
.Pattern = "^\b[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}\b$"
.IgnoreCase = True
End With
retVal = objRegEx.Test(emailAddress)
'get rid of RegEx object '
Set objRegEx = Nothing
ValidEmail = retVal
End Function
Yes, it sure does. Here's Microsoft's documention.
Like other said, yes. I just wanted to put you at the devguru vbscript docs, I find they tend to be the good place to get quick vbscript answers. This is there section on the Regexp object.
VBScript has a built-in RegExp object, which is Microsoft's implementation of JavaScript regular expressions. I have an article about the VBScript RegExp object on my website that explains how to use it.