how to format many emails with regex using vba - excel

With vba, i want to validate many emails between then with semicolon,every mail must end with #customercurrency.com and user can put 2 or 3 or 4 or many emails as he want.
Example : aung#customercurrency.com;thet#customercurrency.com;htoo#customercurrency.com
My code is here.But it might be something wrong.
Public Function ValidateEmailAddressWithSemi(ByRef strEmailAddress As String) As Boolean
'Create Regular expression object
Dim objRegExp As New RegExp
'Set Case insensitive
objRegExp.IgnoreCase = True
objRegExp.pattern = "^\s?([_a-z0-9-]+(.[a-z0-9-]+)#customconcurrency.com)+([;.]([_a-z0-9-]+(.[a-z0-9-]+)#customconcurrency.com)*$"
ValidateEmailAddress = objRegExp.Test(strEmailAddress)
End Function

try this pattern :
"^\s?([_a-z0-9-]+(.[a-z0-9-]+)#customercurrency.com)+([;.]([_a-z0-9-]+(.[a-z0-9-]+)#customercurrency.com))*$"
(mistake in the domain name and a paranthesis is missing)

Related

VB.NET string.contains using wildcards

I Noticed that in a loop inside treeview items , when i am using string.contains method parallel with a textbox that i enter the search string in order to highlight finded nondes , i cant use any wildcard like * or % ... is there any other way to use wildcards ?
What i have tried is having multiple textboxes ex. textbox_x, textbox_y and multiple string.contains in the code string.contains(x) or string.contains(y) but that obviusly doesnt meet my needs because the user may want to use numerous wildcard combinations..
This is a simple function that allows the use of * as jokers at any position
(using regex, here also set to case-insensitive).
Public Shared Function TestSimplePattern(value As String, pattern As String) As Boolean
If String.IsNullOrEmpty(value) Or String.IsNullOrEmpty(pattern) Then Return False
Dim parts = pattern.Split("*")
Dim rxPattern = String.Join(".*?", parts.Select(Function(item) Regex.Escape(item)).ToArray)
rxPattern = "^" & rxPattern & "$"
Return Regex.IsMatch(value, rxPattern, RegexOptions.IgnoreCase)
End Function
Can be used like this:
TestSimplePattern("VB.NET string.contains using wildcards", "*wildcards") ' true
TestSimplePattern("VB.NET string.contains using wildcards", "*string*using*") ' true
TestSimplePattern("VB.NET string.contains using wildcards", "*string*using") ' false

What's the best way to keep regex matches in Excel?

I'm working off of the excellent information provided in "How to use Regular Expressions (Regex) in Microsoft Excel both in-cell and loops", however I'm running into a wall trying to keep the matched expression, rather than the un-matched portion:
"2022-02-14T13:30:00.000Z" converts to "T13:30:00.000Z" instead of "2022-02-14", when the function is used in a spreadsheet. Listed below is the code which was taken from "How to use Regular Expressions (Regex) in Microsoft Excel both in-cell and loops". I though a negation of the strPattern2 would work, however I'm still having issues. Any help is greatly appreciated.
Function simpleCellRegex(Myrange As Range) As String
Dim regEx As New RegExp
Dim strPattern As String
Dim strPattern2 As String
Dim strInput As String
Dim strReplace As String
Dim strOutput As String
strPattern = "^T{0-9][0-9][:]{0-9][0-9][:]{0-9][0-9][0-9][Z]"
strPattern2 = "^(19|20)\d\d([- /.])(0[1-9]|1[012])\2(0[1-9]|[12][0-9]|3[01])"
If strPattern2 <> "" Then
strInput = Myrange.Value
strReplace = ""
With regEx
.Global = True
.MultiLine = True
.IgnoreCase = False
.Pattern = strPattern2
End With
If regEx.test(strInput) Then
simpleCellRegex = regEx.Replace(strInput, strReplace)
Else
simpleCellRegex = "Not matched"
End If
End If
End Function
Replace is very powerful, but you need to do two things:
Specify all the characters you want to drop, if your regexp is <myregexp>, then change it to ^.*?(<myregexp>).*$ assuming you only have one date occurrence in your string. The parentheses are called a 'capturing group' and you can refer to them later as part of your replacement pattern. The ^ at the beginning and the $ at the end ensure that you will only match one occurrence of your pattern even if Global=True. I noticed you were already using a capturing group as a back-reference - you need to add one to the back-reference number because we added a capturing group. Setting up the pattern this way, the entire string will participate in the match and we will use the capturing groups to preserve what we want to keep.
Change your strReplace="" to strReplace="$1", indicating you want to replace whatever was matched with the contents of capturing group #1.
Here is a screenprint from Excel using my RegexpReplace User Defined Function to process your example with my suggestions:
I had to fix up your time portion regexp because you used curly brackets three times where you meant square, and you left out the seconds part completely. Notice by adjusting where you start and end your capturing group parentheses you can keep or drop the T & Z at either end of the time string.
Also, if your program is being passed system timestamps from a reliable source then they are already well-formed and you don't need those long, long regular expressions to reject March 32. You can code both parts in one as
([-0-9/.]{10,10})T([0-9:.]{12,12})Z and when you want the date part use $1 and when you want the time part use $2.

Searching for a word and not a string?

I want to check a file for a particular word the way I have found posted on various forums is to use the following code...
Dim content = My.Computer.FileSystem.ReadAllText(filePath)
If content.Contains("stringToSearch") Then
'Do your stuff
End If
Which is okay until you discover that it will search and match compound words and the likes. For instance If I search for the string light in a file and it's not there but instead the word lightning is, it will still register as having found a match... Is there a way to find and exact word using VB.net?
As mentioned by Andrew Morton, Regex makes this kind of thing very easy. For instance, if you made a function like this:
Public Function ContainsWord(input As String, word As String) As Boolean
Return Regex.IsMatch(input, $"\b{word}\b")
End Function
You could use it like this:
Dim content = My.Computer.FileSystem.ReadAllText(filePath)
If ContainsWord(content, "stringToSearch") Then
'Do your stuff
End If
If you wanted to, you could even make it an extension method on the String type, by putting it in a Module and adding the ExtensionAttribute, like this:
<Extension>
Private Function ContainsWord(input As String, word As String) As Boolean
Return Regex.IsMatch(input, $"\b{word}\b")
End Function
And then you could call it like this:
Dim content = My.Computer.FileSystem.ReadAllText(filePath)
If content.ContainsWord("stringToSearch") Then
'Do your stuff
End If
Another method, using Regex.Matches, which allows to search for a collection of words and returns a Dictionary(Of String, Integer()).
The Dictionary Key represent the matched word, the Value, as an Array of Integers, all the positions inside the File where the word was found.
The extension method requires 2 parameters:
- the path of the file to search
- a boolean value, used to specify whether the search should be case sensitive.
Proposed as an extension method of IEnumerable(Of String):
Dim fileName As String = "[File Path]"
Dim searchWords As String() = {"light", "lighting", "clip", "clipper", "somethingelse"}
Dim result = searchWords.FindWords(fileName, False)
Print a result of the matches found:
result.ToList().ForEach(
Sub(w)
Console.WriteLine($"Word: {w.Key} Positions: {String.Join(", ", w.Value)}")
End Sub)
Extension method:
Imports System.IO
Imports System.Runtime.CompilerServices
Imports System.Text
Imports System.Text.RegularExpressions
Module modIEnumerableExtensions
<Extension()>
Public Function FindWords(words As IEnumerable(Of String),
fileName As String,
caseSentive As Boolean) As Dictionary(Of String, Integer())
Dim pattern As StringBuilder = New StringBuilder()
pattern.Append(String.Concat(words.Select(Function(w) $"\b{w}\b|")))
Dim options As RegexOptions = RegexOptions.Compiled Or
If(caseSentive, RegexOptions.Multiline, RegexOptions.IgnoreCase Or RegexOptions.Multiline)
Dim regx As New Regex(pattern.ToString().TrimEnd("|"c), options)
Dim matches As MatchCollection = regx.Matches(File.ReadAllText(fileName))
Dim groups = matches.OfType(Of Match).
GroupBy(Function(g) g.Value).
ToDictionary(Function(g) g.Key, Function(g) g.Select(Function(m) m.Index).ToArray())
Return groups
End Function
End Module
The shortest and fastest way to do this is using ReadLines with LINQ queries, specialy when you are working with a large files.
Dim myword As String = "Book"
Dim reg = New Regex("\b" & myword & "\b", RegexOptions.IgnoreCase)
Dim res = From line In File.ReadLines(largeFileName)
Where reg.IsMatch(line)
If your file containts "Book", "Books", "Book." and "Book," the results will be:
Book
Book,
Book.
And you can working with results as following
TextBox1.Text = resLines.Count
Or
TextBox1.Text = resLines(0)
Edited to make it consering "." and "," etc.

Excel formula function to remove spaces between characters

In Excel sheet i did a form that customer need to fill out, i have a cell that the customer need to enter his Email Address, I need to data validate the cell as much i can and am nearly success this is what i did:
' this formula is for email structuring
=ISNUMBER(MATCH("*#*.???",A5,0))
' this formula to check if there is spaces at start and the end
=IF(LEN(A5)>LEN(TRIM(A5)),FALSE,TRUE)
But if i right for example (admin#ad min.com) the second formula will not detect the space between the email address, any clue?
Use SUBSTITUTE()
=IF(LEN(A5)>LEN(SUBSTITUTE(A5," ","")),FALSE,TRUE)
How about:
=IF(LEN(A5)>LEN(SUBSTITUTE(A5," ","")),FALSE,TRUE)
based on Jeeped's comment:
=A5=SUBSTITUTE(A5," ","")
You can use VBA to perform validation using regular expressions - after removing any spaces.
Option 1
Returning a Boolean True/False
Public Function validateEmail(strEmail As String) As Boolean
' Remove spaces
strEmail = Replace(strEmail, " ", "")
' Validate email using regular expressions
With CreateObject("VBScript.RegExp")
.ignorecase = True
.Pattern = "^[-.\w]+#[-.\w]+\.\w{2,5}$"
If .test(strEmail) Then validateEmail = True
End With
End Function
This can be used as a normal worksheet function such as:
=validateEmail("yourEmail#test.com")
=validateEmail($A1)
Can also be used in VBA as well
debug.print validateEmail("yourEmail#test.com")
Option 2
Returning the email itself, or return False
If you would prefer that it returns the validated email instead of a Boolean (true/False), then you can do something like:
Public Function validateEmail(strEmail As String) As Variant
' Remove spaces
strEmail = Replace(strEmail, " ", "")
' Validate email using regular expressions
With CreateObject("VBScript.RegExp")
.ignorecase = True
.Pattern = "^[-.\w]+#[-.\w]+\.\w{2,5}$"
If .test(strEmail) Then
validateEmail = strEmail
Else
validateEmail = False
End If
End With
End Function
So, using in a worksheet function for example, using =validateEmail("yourEmail # test.com") will return the string: yourEmail#test.com. However, if the email is invalid such as validateEmail("yourEmailtest.com") then it will return False.
Why use Regular Expressions? Checking for a simple # in the string to validate an email is only a minimal workaround. A string input such as ()#&&*^$#893---------6584.ido would match your =ISNUMBER(MATCH("*#*.???",A5,0)) formula, yet that is obviously not a valid email. Obviously there is no way to 100% validate an email - however, this does a decent job at at the very least ensuring the email could be valid.

replace multiple cell value from a group of strings

Hi I want to replace multiple values in one for example :
sunny 91878656 rere
vicky 91864567 gfgf
honey 91941561 ytyt
monika 98887888 hjhj
NOw if I want to replace the following two values together with space:
91941561
98887888
How can I do it ?
I dont want to do simple find and replace as this is just an exmaple I have a list of over 12000 records and the numbers which needs to be replaced are more than 900
the reason i want to replace is they are not valid anymore.
also is it possible to remove whole record like if 91941561 is found whole of the record should be deleted or replaced with space like:
honey 91941561 ytyt
monika 98887888 hjhj
thanks
You may use the Regular expression. Below is a sample code
Sub test()
Dim str_demo As String
str_demo = "monika 98887888 hjhj"
MsgBox getString(str_demo)
End Sub
Function getString(ByVal str As String) As String
Dim objRegEx As Object
Set objRegEx = CreateObject("VBScript.RegExp")
objRegEx.IgnoreCase = True
objRegEx.Global = True
objRegEx.Pattern = "[a-zA-Z]"
Set allMatches = objRegEx.Execute(str)
For i = 0 To allMatches.Count - 1
result = result & allMatches.Item(i)
Next
getString = result
End Function

Resources