Excel Vba-Similar Function - vba

I'm so confused in resolving this:
In VBA syntax there is this function:
If Left("abcdef",3)="abc" then
Msgbox "True"
This function is too simple but is there any way for e.g.
To have something like this
If left("abcdef",3) is in ["A".."Z"] or if left("1265avd0",2) is in [1..9]
Which mean checking if left ("abcdef",3) which is equal to "abc" is in this Interval ["A".."Z"] or checking if the left("123avd0",2) is numeric and is in the interval of [1..9]
Hope you are understading what I want to do
Can anyone Light me in doing This?

You can use the Like operator for this simple type of comparison.
Option Explicit
Option Compare Text 'for case insensitive matching
Sub dural()
Const S1 As String = "abcdef"
Const S2 As String = "1265avd0"
Debug.Print Left(S1, 3) Like "[A-Z][A-Z][A-Z]"
Debug.Print Left(S2, 2) Like "[1-9][1-9]"
End Sub
Both will return TRUE in this instance.
As pointed out by #chrisneilsen, the comparisons can be simplified to:
S1 Like "[A-Z][A-Z][A-Z]*"
S2 Like "[1-9][1-9]*"
And you can test for either with something like:
If Left(myString, 3) Like "[A-Z][A-Z][A-Z]" or _
Left(myString, 2) Like "[1-9][1-9]" then
'do something
End if
And in the simplified version:
If myString Like "[A-Z][A-Z][A-Z]*" or _
myString Like "[1-9][1-9]*" then
'do something
End if
More complex pattern matching can be done using Regular Expressions.
If you prefer to not set Option Compare then change the alpha patterns to "[A-Za-z]"

You can use Regular Expressions ("RegEx") for this.
The pattern has a non-capturing group (?:...) that can determine if the start of the string ^ contains either three letters of any case: [a-zA-Z]{3} or | two digits \d{2}.
If either criterion is met, then the MsgBox will return True, otherwise, it returns False.
Sub test()
Dim RegEx As New RegExp, testString As String
testString = "53bcko390872"
With RegEx
.Pattern = "^(?:[a-zA-Z]{3}|\d{2})"
MsgBox .test(testString) 'will prompt True/False
End With
End Sub
You can replace the MsgBox line with something useful, such as
If .test(testString) [= True] Then...
Click Here for a live demo on the regex working (optional).
Note that you will need to set a reference to Microsoft VBScript Regular Expressions x.x

Related

Block Finder - Like Function

I have a large string (more than 255 char) called strBlockText. This string includes random text and block numbers. The block numbers should to be in the format ###Block####-## (IE: 245Block6533-56) but sometimes someone enters the wrong block number format in the text - for example ##Block####-## or ###Block###-## or ##Block###-##...etc.
**Note, this is for plain text only.
I want to write a function that will be able to state, "Wrong block number format identified." when the block number is fat fingered.
This is the text I'm using as a sample:
This is a Test that we need to figure out why this isn’t working.
24Block1234-23 This is a Test that we need to figure out why this
isn’t working. 245Block4234-14 This is a Test that we need to figure
out why this isn’t working. This is a Test that 245Block6533-56 we
need to figure out why this isn’t working.
This is the code...that I feel should work but isn't:
Dim strBlockText As String
Dim strBlockCheck As String
If (((strBlockText Like "*##Block####-##*") or _
(strBlockText Like "*###Block###-##*") or _
(strBlockText Like "*##Block###-##*")) And _
(Not strBlockText Like "*###Block####-##*")) Then
strBlockCheck = "Wrong block number format identified."
Else
strBlockCheck = "Block number format acceptable."
End If
Would it be better to use a regex for this instead of like?...is there a reason like isn't working?
Consider this Sub using RegExp object with late binding:
Sub testRegExp2(strS)
Dim regexOne As Object, Matches As Object, Match As Object
'Set regexOne = New RegExp
Set regexOne = CreateObject("VBScript.RegExp")
regexOne.Pattern = "[0-9]+Block[0-9]+-[0-9]+"
regexOne.Global = True
Set Matches = regexOne.Execute(strS)
For Each Match In Matches
If Not Match Like "###Block####-##" Then
Debug.Print "Wrong block number format identified: " & Match
Else
Debug.Print "Block number format acceptable: " & Match
End If
Next
End Sub

VB.NET - Replace string using or statement

I am having trouble, here is my code.
TextBox2.Text = TextBox1.Text.Replace("a" Or "A", "test")
Simply what I have failed to find a straight answer for. I want to find lowercase "a" and replace it with "test". If it finds a capital "A" I also want to replace it with "test". When I try and OR statement it throws an error. I am looking for a solution, thank you for your time.
You just can't apply and Or operator between two strings.
If you don't want to learn Regex you can concatenate infinite .replace() calls as the return value is a new string.
If you don't care of upper or lower and just want to replace the a character (eather upper and lower) you can use .toUpper() or .toLower() on the input string before passing it to .replace()
Test 1:
Dim input = "abcABC"
output = input.replace("a", "-").replace("A", "-")
Test 2:
Dim input = "abcABC"
output = input.toLower().replace("a", "-")
Test 1 will output this string: "-bc-BC"
Test 2 will output this string: "-bc-bc"
you can simply use a Regex like :
Dim rgx As New RegularExpressions.Regex("[aA]")
If rgx.IsMatch(TextBox1.Text) Then
TextBox2.Text = "test"
End If
OR use this if statement
If TextBox1.text.Contains("a") Or TextBox1.text.Contains("A") Then
TextBox2 = "test"
End If
Or just go to the official documentation of [string.replace] site
as TnTinMn suggested , same case can be found there
TextBox2.Text = TextBox1.Text.Replace("a", "test").Replace("A","test)

How to extract numbers UNTIL a space is reached in a string using Excel 2010?

I need to pull the code from the following string: 72381 Test 4Dx for Worms. The code is 72381 and the function that I'm using does a wonderful job of pulling ALL the numbers from a string and gives me back 723814, which pulls the 4 from the description of the code. The actual code is only the 72381. The codes are of varying length and are always followed by a space before the description begins; however there are spaces in the descriptions as well. This is the function I am using that I found from a previous search:
Function OnlyNums(sWord As String)
Dim sChar As String
Dim x As Integer
Dim sTemp As String
sTemp = ""
For x = 1 To Len(sWord)
sChar = Mid(sWord, x, 1)
If Asc(sChar) >= 48 And _
Asc(sChar) <= 57 Then
sTemp = sTemp & sChar
End If
Next
OnlyNums = Val(sTemp)
End Function
If the first character in the description part of your string is never numeric, you could use the VBA Val(string) function to return all of the numeric characters before the first non-numeric character.
Function GetNum(sWord As String)
GetNum = Val(sWord)
End Function
See the syntax of the Val(string) function for full details of it's usage.
You're looking for the find function.. Example:
or in VBA instr() and left()
Since you know the pattern is always code followed by space just use left of the string for the number of characters to the first space found using instr. Sample in immediate window above. Loop is going to be slow, and while it may validate they are numeric why bother if you know pattern is code then space?
In similar situations in C# code, I leave the loop early after finding the first instance of a space character (32). In VBA, you'd use Exit For.
You can get rid of the function altogether and use this:
split("72381 Test 4Dx for Worms"," ")(0)
This will split the string into an array using " " as the split char. Then it shows us address 0 in the array (the first element)
In the context of your function if you are dead set on using one it is this:
Function OnlyNums(sWord As String)
OnlyNums = Split(sWord, " ")(0)
End Function
While I like the simplicity of Mark's solution, you could use an efficient parser below to improve your character by character search (to cope with strings that don't start with numbers).
test
Sub test()
MsgBox StrOut("72381 Test 4Dx")
End Sub
code
Function StrOut(strIn As String)
Dim objRegex As Object
Set objRegex = CreateObject("vbscript.regexp")
With objRegex
.Pattern = "^(\d+)(\s.+)$"
If .test(strIn) Then
StrOut = .Replace(strIn, "$1")
Else
StrOut = "no match"
End If
End With
End Function

Strip out non-numeric characters in SELECT

In an MS Access 2007 project report, I have the following (redacted) query:
SELECT SomeCol FROM SomeTable
The problem is, that SomeCol apparently contains some invisible characters. For example, I see one result returned as 123456 but SELECT LEN(SomeCol) returns 7. When I copy the result to Notepad++, it shows as ?123456.
The column is set to TEXT. I have no control over this data type, so I can't change it.
How can I modify my SELECT query to strip out anything non-numeric. I suspect RegEx is the way to go... alternatively, is there a CAST or CONVERT function?
You mentioned using a regular expression for this. It is true that Access' db engine doesn't support regular expressions directly. However, it seems you are willing to use a VBA user-defined function in your query ... and a UDF can use a regular expression approach. That approach should be simple, easy, and faster performing than iterating through each character of the input string and storing only those characters you want to keep in a new output string.
Public Function OnlyDigits(ByVal pInput As String) As String
Static objRegExp As Object
If objRegExp Is Nothing Then
Set objRegExp = CreateObject("VBScript.RegExp")
With objRegExp
.Global = True
.Pattern = "[^\d]"
End With
End If
OnlyDigits = objRegExp.Replace(pInput, vbNullString)
End Function
Here is an example of that function in the Immediate window with "x" characters as proxies for your invisible characters. (Any characters not included in the "digits" character class will be discarded.)
? OnlyDigits("x1x23x")
123
If that is the output you want, just use the function in your query.
SELECT OnlyDigits(SomeCol) FROM SomeTable;
There is no RegEx in Access, at least not in SQL. If you venture to VBA, you might as well use a custom StripNonNumeric VBA function in the SQL statement.
e.g. SELECT StripNonNumeric(SomeCol) as SomeCol from SomeTable
Function StripNonNumeric(str)
keep = "0123456789"
outstr = ""
For i = 1 to len(str)
strChar = mid(str,i,1)
If instr(keep,strChar) Then
outstr = outstr & strChar
End If
Next
StripNonNumeric = outstr
End Function
You can do it all in a query, combining this question with your previous question, you get:
SELECT IIf(IsNumeric([atext]),
IIf(Len([atext])<4,Format([atext],"000"),
Replace(Format(Val([atext]),"#,###"),",",".")),
IIf(Len(Mid([atext],2))<4,Format(Mid([atext],2),"000"),
Replace(Format(Val(Mid([atext],2)),"#,###"),",","."))) AS FmtNumber
FROM Table AS t;
Public Function fExtractNumeric(strInput) As String
' Returns the numeric characters within a string in
' sequence in which they are found within the string
Dim strResult As String, strCh As String
Dim intI As Integer
If Not IsNull(strInput) Then
For intI = 1 To Len(strInput)
strCh = Mid(strInput, intI, 1)
Select Case strCh
Case "0" To "9"
strResult = strResult & strCh
Case Else
End Select
Next intI
End If
fExtractNumeric = strResult
End Function

VB.NET - If string contains "value1" or "value2"

I'm wondering how I can check if a string contains either "value1" or "value2"?
I tried this:
If strMyString.Contains("Something") Then
End if
This works, but this doesn't:
If strMyString.Contains("Something") or ("Something2") Then
End if
This gives me the error that conversion from string to Long can't be done.
If I put the or ("Something2") inside the parenthesis of the first one, it gives me the error that the string cannot be converted to Boolean.
So how can I check if the string contains either "string1" or "string2" without having to write too much code?
You have to do it like this:
If strMyString.Contains("Something") OrElse strMyString.Contains("Something2") Then
'[Put Code Here]
End if
You need this
If strMyString.Contains("Something") or strMyString.Contains("Something2") Then
'Code
End if
In addition to the answers already given it will be quicker if you use OrElse instead of Or because the second test is short circuited. This is especially true if you know that one string is more likely than the other in which case place this first:
If strMyString.Contains("Most Likely To Find") OrElse strMyString.Contains("Less Likely to Find") Then
'Code
End if
Here is the alternative solution to check whether a particular string contains some predefined string. It uses IndexOf Function:
'this is your string
Dim strMyString As String = "aaSomethingbb"
'if your string contains these strings
Dim TargetString1 As String = "Something"
Dim TargetString2 As String = "Something2"
If strMyString.IndexOf(TargetString1) <> -1 Or strMyString.IndexOf(TargetString2) <> -1 Then
End If
NOTE: This solution has been tested with Visual Studio 2010.
You have ("Something2") by itself - you need to test it so a boolean is returned:
If strMyString.Contains("Something") or strMyString.Contains("Something2") Then
If strMyString.Contains("Something") or strMyString.Contains("Something2") Then
End if
The error indicates that the compiler thinks you want to do a bitwise OR on a Boolean and a string. Which of course won't work.
If strMyString.Tostring.Contains("Something") or strMyString.Tostring.Contains("Something2") Then
End if
I've approached this in a different way. I've created a function which simply returns true or false..
Usage:
If FieldContains("A;B;C",MyFieldVariable,True|False) then
.. Do Something
End If
Public Function FieldContains(Searchfor As String, SearchField As String, AllowNulls As Boolean) As Boolean
If AllowNulls And Len(SearchField) = 0 Then Return True
For Each strSearchFor As String In Searchfor.Split(";")
If UCase(SearchField) = UCase(strSearchFor) Then
Return True
End If
Next
Return False
End Function
If you want to disregard whether the text is uppercase or lowercase, use this:
If strMyString.ToUpper.Contains("TEXT1") OrElse strMyString.ToUpper.Contains("TEXT2") Then
'Something
End if
Interestingly, this solution can break, but a workaround:
Looking for my database called KeyWorks.accdb which must exist:
Run this:
Dim strDataPath As String = GetSetting("KeyWorks", "dataPath", "01", "") 'get from registry
If Not strDataPath.Contains("KeyWorks.accdb") Then....etc.
If my database is named KeyWorksBB.accdb, the If statement will find this acceptable and exit the If statement because it did indeed find KeyWorks and accdb.
If I surround the If statement qualifier with single quotes like 'KeyWorks.accdb', it now looks for all the consecutive characters in order and would enter the If block because it did not match.