Check if string is uppercase and numbers - regex

I want to check if a string contains only uppercase letters and numbers. I have attempted to solve this using RegExp and what I have so far is:
Function CheckForInvalidChars()
dim b
Set re = New RegExp
re.Pattern = "[A-Z_0-9]"
b = re.Test("eS")
msgbox b
End Function
However the variable "b" returns true since I guess it finds a match in the "S" although I want that particular string to return false since not all letters are uppercase. How would I go about achieving this?
I have tried to do this with functions as well using IsNumeric but can't find a IsUpperCase.

Generally speaking, if you want to match whole string using regex, you will usually end up using ^ and $ to describe the start and end of string.
Also, just [A-Z_0-9] matches a single character.
Assuming you don't allow whitespaces, ^[A-Z_0-9]*$ would be the regex you're looking for.

If UCase(s) <> s then there is at least one lower case letter in the string s.

I'd recommend to just UCase the string if you want to enforce uppercase letters. Then you can simplify the check to this:
Function CheckForInvalidChars(s)
Set re = New RegExp
re.Pattern = "^\w+$"
CheckForInvalidChars = re.Test(s)
End Function
teststring = InputBox("Input something")
teststring = UCase(teststring)
WScript.Echo "" & CheckForInvalidChars(teststring)
The escape sequence \w matches word characters, i.e. uppercase letters, lowercase letters (ruled out due to the prior UCase), digits, and underscores. The + rules out empty strings by requiring at least one word character.

#Andris is right, correct the regular expression as follows:
Function CheckForInvalidChars()
dim b
Set re = New RegExp
re.Pattern = "^[A-Z_0-9]*$"
b = re.Test("eS")
msgbox b
End Function

Related

Excel VBA Regex Check For Repeated Strings

I have some user input that I want to validate for correctness. The user should input 1 or more sets of characters, separated by commas.
So these are valid input
COM1
COM1,COM2,1234
these are invalid
COM -- only 3 characters
COM1,123 -- one set is only 3 characters
COM1.1234,abcd -- a dot separator not comma
I googled for a regex pattern to this and found a possible pattern that tested for a recurring instance of any 3 characters, and I modified like so
/^(.{4,}).*\1$/
but this is not finding matches.
I can manage the last comma that may or may not be there before passing to the test so that it is always there.
Preferably, I would like to test for letters (any case) and numbers only, but I can live with any characters.
I know I could easily do this in straight VBA splitting the input on a comma delimiter and looping through each character of each array element, but regex seems more efficient, and I will have more cases than have slightly different patterns, so parameterising the regex for that would be better design.
TIA
I believe this does what you want:
^([A-Z|a-z|0-9]{4},)*[A-Z|a-z|0-9]{4}$
It's a line beginning followed by zero or more groups of four letters or numbers ending with a comma, followed by one group of four letters or number followed by an end-of-line.
You can play around with it here: https://regex101.com/r/Hdv65h/1
The regular expression
"^[\w]{4}(,[\w]{4})*$"
should work.
You can try this to see whether it works for all your cases using the following function. Assuming your test strings are in cells A1 thru A5 on the spreadsheet:
Sub findPattern()
Dim regEx As New RegExp
regEx.Global = True
regEx.IgnoreCase = True
regEx.Pattern = "^[\w]{4}(,[\w]{4})*$"
Dim i As Integer
Dim val As String
For i = 1 To 5:
val = Trim(Cells(i, 1).Value)
Set mat = regEx.Execute(val)
If mat.Count = 0 Then
MsgBox ("No match found for " & val)
Else
MsgBox ("Match found for " & val)
End If
Next
End Sub

How to loop a regex.match or add a range to String.Contains()

I've built a password Generator:
Public Function PassGen()
Dim pool As String = "0123456789abcdefghijklmnopqrstuvwxzyABCDEFGHIJKLMNOPQRSTUVWXYZ+#*#%&/()?!$-"
Dim rnd As New Random
Dim result As String
Dim i As Integer = 0
Do Until i = 10
result &= pool(rnd.Next(0, pool.Length))
i = i + 1
Loop
Return result
End Function
Now I'd like to check if the generated password contains a number, upper- and lowercase and special characters. If the generated password doesn't contain those 4 things, it should generate another password and check it again and so on.
I tried to loop a Regex.Match:
Dim text As String = PassGen()
Do Until Regex.Match(text, "^[0-9]$")
text = PassGen()
Loop
What didnt work as it wont let me loop a regex.match().
I also tried it with String.Contains(). But as far as I know the Contains-method can only check for one string and not for a range or a type(like Integer).
Is there a possibility to check my password for those four string-ranges or do I have to modify my function that it has to use one of each?
You could use the LIKE keyword in VB. The LIKE is like a mini-regex built in into VB.NET.
If text Like "*[A-Z]*" AndAlso text Like "*[a-z]*" AndAlso text Like "*[0-9]*" AndAlso text Like "*[+#*#%&/()?!$-]*" Then
' it is a valid password
Else
' password doesn't match required constraints... do whatever to regenerate it here...
End If
You can use one regex to check the password strength:
Do Until System.Text.RegularExpressions.Regex.IsMatch(text, "(?s)^(?=.*\d)(?=.*\p{Ll})(?=.*\p{Lu})(?=.*\W)")
The \W matches all special characters other than letters, digits and _, thus you have a much wider scope with it than manually defining a character class like [+#*#%&/()?!$-].
The (?s) is an inline singleline modifier to force . to match a newline, too. The \d matches a digit, the \p{Ll} matches a lowercase letter, and \p{Lu} matches an uppercase letter. The lookaheads (?=...) are executed one after another upon success. If one of them returns false, the whole match is failed.

How to test for specific characters with regex in VBA

I need to test for a string variable to ensure it matches a specific format:
XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
...where x can be any alphanumerical character (a - z, 0 - 9).
I've tried the following, but it doesn't seem to work (test values constantly fail)
If val Like "^([A-Za-z0-9_]{8})([-]{1})([A-Za-z0-9_]{4})([-]{1})([A-Za-z0-9_]{4})([-]{1})([A-Za-z0-9_]{4})([-]{1})([A-Za-z0-9_]{12})" Then
MsgBox "OK"
Else
MsgBox "FAIL"
End If
.
fnCheckSubscriptionID "fdda752d-32de-474e-959e-4b5bf7574436"
Any pointers? I don't mind if this can be achieved in vba or with a formula.
You are already using the ^ beginning-of-string anchor, which is terrific. You also need the $ end-of-string anchor, otherwise in the last group of digits, the regex engine is able to match the first 12 digits of a longer group of digits (e.g. 15 digits).
I rewrote your regex in a more compact way:
^[A-Z0-9]{8}-(?:[A-Z0-9]{4}-){3}[A-Z0-9]{12}$
Note these few tweaks:
[-]{1} can just be expressed with -
I removed the underscores as you say you only want letters and digits. If you do want underscores, instead of [A-Z0-9]{8} (for instance), you can just write \w{8} as \w matches letters, digits and underscores.
Removed the lowercase letters. If you do want to allow lowercase letters, we'll turn on case-insensitive mode in the code (see line 3 of the sample code below).
No need for (capturing groups), so removed the parentheses
We have three groups of four letters and a dash, so wrote (?:[A-Z0-9]{4}-) with a {3}
Sample code
Dim myRegExp, FoundMatch
Set myRegExp = New RegExp
myRegExp.IgnoreCase = True
myRegExp.Pattern = "^[A-Z0-9]{8}-(?:[A-Z0-9]{4}-){3}[A-Z0-9]{12}$"
FoundMatch = myRegExp.Test(SubjectString)
You can do this either with a regular expression, or with just native VBA. I am assuming from your code that the underscore character is also valid in the string.
To do this with native VBA, you need to build up the LIKE string since quantifiers are not included. Also using Option Compare Text makes the "like" action case insensitive.
Option Explicit
Option Compare Text
Function TestFormat(S As String) As Boolean
'Sections
Dim S1 As String, S2_4 As String, S5 As String
Dim sLike As String
With WorksheetFunction
S1 = .Rept("[A-Z0-9_]", 8)
S2_4 = .Rept("[A-Z0-9_]", 4)
S5 = .Rept("[A-Z0-9_]", 12)
sLike = S1 & .Rept("-" & S2_4, 3) & "-" & S5
End With
TestFormat = S Like sLike
End Function
With regular expressions, the pattern is simpler to build, but the execution time may be longer, and that may make a difference if you are processing very large amounts of data.
Function TestFormatRegex(S As String) As Boolean
Dim RE As Object
Set RE = CreateObject("vbscript.regexp")
With RE
.Global = True
.MultiLine = True
.Pattern = "^\w{8}(?:-\w{4}){3}-\w{12}$"
TestFormatRegex = .test(S)
End With
End Function
Sub Test()
MsgBox fnCheckSubscriptionID("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")
End Sub
Function fnCheckSubscriptionID(strCont)
' Tools - References - add "Microsoft VBScript Regular Expressions 5.5"
With New RegExp
.Pattern = "^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$"
.Global = True
.MultiLine = True
fnCheckSubscriptionID = .Test(strCont)
End With
End Function
In case of any problems with early binding you can use late binding With CreateObject("VBScript.RegExp") instead of With New RegExp.

VBScript Regular Expression

Need help building a VBScript regex that checks for a valid computer name and returns only invalid characters. String can contain numbers, upper and lower case letters, and (-) sign only. It can't start or end with (-) and cannot be only numbers.
Valid (Returns no match):
computer
Computer8
8Computer
Com8puter
Com-Puter
Computer-123
Invalid (Returns a match to invalid characters):
123
-computer
computer-
com*puter
PC&123
According to this: http://msdn.microsoft.com/en-us/library/ms974570.aspx VBScript has its own regex syntactic flavour. Note that NetBIOS computer names have a length limit of 15.
Then it should be "^\w[\w-]{0,14}$"
That RegEx satisfies all of the requirements except the "is all numbers". That can be done by running a second regex "^\d+$".
In code:
Dim regexValid, regexNumber
Set regexValid = New RegExp
Set regexNumber = New RegExp
regexValid.Global = True
regexValid.IgnoreCase = True
regexNumber.Global = True
regexNumber.IgnoreCase = True
regexValid.Pattern = "^\w[\w\-]{0,14}$"
regexNumber.Pattern = "^\d+$"
Dim inputString
inputString = InputBox("Computer name?")
If regexValid.Test( inputString ) And Not regexNumber.Test( inputString ) Then
' It's a valid computer name string
Else
' It's invalid
End If
Hmm, this is the first VBScript I've written this year.
I ended up switching the valid and invalid returns. I also ended up using two different RegEx strings. The first is:
^[0-9a-zA-Z]{1,}[-]*[0-9a-zA-Z]{1,}$
This doesn't allow the (-) at the beginning or end and requires all numbers, letters, or (-). It also requires a string of at least two characters.
The second is:
"[a-zA-Z]"
This makes sure there is at least one letter included.
Something like this /^([0-9]|[a-zA-Z]){1,}[a-zA-Z0-9-]+([0-9]|[a-zA-Z]){1,}$/

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.