I am looking to see if a string has a comma or not.
Lets say I have two usernames "David , Boon" and "David Blind".
I need to write an if loop based on the conditions whether ',' exists in the User name or not. Is there a way to check that ? Something like Contains in .Net
Kindly share your thoughts.
You can use the InStr function to check the presence/location of one string within another:
Dim myVar As String
myVar = "foo,bar"
If InStr(1, myVar, ",") > 0 Then
'There was a comma
End If
Here's two,
if cbool(instr(1, mystring, chr(44))) then
...
if cbool(ubound(split(mystring, chr(44)))) then
...
You may try the following approach in your code...
If InStr(Range("A1").Value, ",") Then
MsgBox "Comma Exists", vbInformation
Else
MsgBox "No comma exists", vbExclamation
End If
Or just have a Function like below...
Function CommaExists(ByVal Rng As Range) As Boolean
If InStr(Rng.Value, ",") Then
CommaExists = True
End If
End Function
And call the function in your sub routine like this...
Sub Test()
If CommaExists(Range("A1")) Then
MsgBox "Comma found in the string.", vbInformation
Else
MsgBox "No Comma found in the string.", vbExclamation
End If
End Sub
I think that most readable option (subjective opinion, but worth to mention) here is a Like operator:
Dim myVar As String
myVar = "foo,bar"
If myVar Like "*,*" Then
'There was a comma
End If
Related
I want to find if a string contains a ","(comma) in it. Do we have any other option other than reading char-by-char?
Use the Instr function (old version of MSDN doc found here)
Dim pos As Integer
pos = InStr("find the comma, in the string", ",")
will return 15 in pos
If not found it will return 0
If you need to find the comma with an excel formula you can use the =FIND(",";A1) function.
Notice that if you want to use Instr to find the position of a string case-insensitive use the third parameter of Instr and give it the const vbTextCompare (or just 1 for die-hards).
Dim posOf_A As Integer
posOf_A = InStr(1, "find the comma, in the string", "A", vbTextCompare)
will give you a value of 14.
Note that you have to specify the start position in this case as stated in the specification I linked: The start argument is required if compare is specified.
You can also use the special word like:
Public Sub Search()
If "My Big String with, in the middle" Like "*,*" Then
Debug.Print ("Found ','")
End If
End Sub
There is also the InStrRev function which does the same type of thing, but starts searching from the end of the text to the beginning.
Per #rene's answer...
Dim pos As Integer
pos = InStrRev("find the comma, in the string", ",")
...would still return 15 to pos, but if the string has more than one of the search string, like the word "the", then:
Dim pos As Integer
pos = InStrRev("find the comma, in the string", "the")
...would return 20 to pos, instead of 6.
Building on Rene's answer, you could also write a function that returned either TRUE if the substring was present, or FALSE if it wasn't:
Public Function Contains(strBaseString As String, strSearchTerm As String) As Boolean
'Purpose: Returns TRUE if one string exists within another
On Error GoTo ErrorMessage
Contains = InStr(strBaseString, strSearchTerm)
Exit Function
ErrorMessage:
MsgBox "The database has generated an error. Please contact the database administrator, quoting the following error message: '" & Err.Description & "'", vbCritical, "Database Error"
End
End Function
You wouldn't really want to do this given the existing Instr/InstrRev functions but there are times when it is handy to use EVALUATE to return the result of Excel worksheet functions within VBA
Option Explicit
Public Sub test()
Debug.Print ContainsSubString("bc", "abc,d")
End Sub
Public Function ContainsSubString(ByVal substring As String, ByVal testString As String) As Boolean
'substring = string to test for; testString = string to search
ContainsSubString = Evaluate("=ISNUMBER(FIND(" & Chr$(34) & substring & Chr$(34) & ", " & Chr$(34) & testString & Chr$(34) & "))")
End Function
Everything is working except for that little comma in the 5th word. How to remove that? My code is as follows.
The text looks like this: The data as of 20.12.2019, and so on.
I only want 20.12.2019 without that comma. Any clue? Thanks.
Public Function FindWord(Source As String, Position As Integer)
Dim arr() As String
arr = VBA.Split(Source, " ")
xCount = UBound(arr)
If xCount < 1 Or (Position - 1) > xCount Or Position < 0 Then
FindWord = ""
Else
FindWord = arr(Position - 1)
End If
End Function
subroutine calls the function.
Sub InsertDate()
Sheets("Sheet1").Range("B3").Value = FindWord(Sheets("Sheet2").Range("A2"), 5)
End Sub
So just for fun, a short introduction to regular expressions (which, by no means, I am an expert in):
Sub Test()
Dim str As String: str = "The data as of 20.12.2019, and so on."
Dim regex As Object: Set regex = CreateObject("VBScript.RegExp")
regex.Pattern = "\b(\d{2}.\d{2}.\d{4})"
regex.Global = True
Debug.Print regex.Execute(str)(0)
End Sub
This would be good practice if your string won't follow that same pattern all the time. However when it does, there are some other good alternatives mentioned in comments and answers.
One option is to Replace:
Sub InsertDate()
With Sheets("Sheet1").Range("B3")
.Value = FindWord(Sheets("Sheet2").Range("A2"), 5)
.Value = Replace(.Value, ",", "")
End With
End Sub
This is still text-that-looks-like-a-date, so you can call DateValue to convert it.
.Value = Replace(.Value, ",", "")
.Value = DateValue(.Value) '<~ add this line
I am trying to utilize Vlookup function, according to the Textbox1 value user put in in Userform Guntest, automatically looking for corresponding features of the gun.
However the program currently doesn't run as it reminds me
'Runtime error '1004', method 'Range of object' _Global' failed.
The error appears on Retrieve1=…
I will be appreciated if you could help me to check where the problem is as I have really limited knowledge and experience on using VBA.
Thanks in advance.
It looks like some objects is undefined but I can't figure out where.
The module 1 code is:
Public Guncode As String
Option Explicit
Sub Test()
Call Vlookup
End Sub
Sub Vlookup()
Dim Retrieve1 As String
Dim Retrieve2 As String
Dim FinalRow As Long
Dim FinalColumn As Long
Dim WholeRange As String
If GunTest.TextBox1 = "" Then
Exit Sub
If GunTest.TextBox1 <> "" Then
MsgBox Guncode
End If
End If
With Sheets(1)
FinalRow = Range("A65536").End(xlUp).Row
FinalColumn = Range("IV1").End(xlToLeft).Column
WholeRange = "A2:" & CStr(FinalColumn) & CStr(FinalRow)
Retrieve1 = Application.WorksheetFunction.Vlookup(Trim(Guncode), Range(WholeRange), 1, False) 'Locate specific tool according to QR code number
Retrieve2 = Application.WorksheetFunction.Vlookup(Trim(Guncode), Range(WholeRange), 5, False) 'Locate specific gun type according to QR code number
If Guncode = "" Then
MsgBox "This gun doesn't exist in database!"
Else
MsgBox "The tool number is:" & Retrieve1 & vbCrLf & "The gun type is:" & Retrieve2
End If
End With
End Sub
The userform code is:
Option Explicit
Private Sub Label1_Click()
End Sub
Private Sub CommandButton1_Click()
If TextBox1 = "" Then Exit Sub 'Set condition 1 of exiting the program
Guncode = GunTest.TextBox1
With Me
Call Module1.Test
End With
End Sub
Private Sub PartID_Click()
End Sub
Private Sub TextBox1_Change()
End Sub
Private Sub UserForm_Click()
End Sub
It should run properly but it doesn't. Any help would be appreciated, thanks!
First off, you were passing in a number as the column letter value. CSTR() doesnt magically transform it into the letter equivalent but I like your enthusiasm.
Second, your method will bomb if the value isnt found - so you'll need to write your own error handling for it.
Sub Vlookup()
Dim Retrieve1 As String
Dim Retrieve2 As String
Dim FinalRow As Long
Dim FinalColumn As Long
Dim WholeRange As String
Dim vArr
Dim col_Letter As String
If GunTest.TextBox1 = "" Then
Exit Sub
If GunTest.TextBox1 <> "" Then
MsgBox Guncode
End If
End If
With ThisWorkbook.Sheets("Sheet1")
FinalRow = .Range("A65536").End(xlUp).Row
FinalColumn = .Range("IV1").End(xlToLeft).Column
vArr = Split(Cells(1, FinalColumn).Address(True, False), "$")
col_Letter = vArr(0)
WholeRange = "A2:" & col_Letter & CStr(FinalRow) '<---- you were passing a number in as the column value
Retrieve1 = Application.WorksheetFunction.Vlookup(Trim(Guncode), .Range(WholeRange), 1, False) 'Locate specific tool according to QR code number
Retrieve2 = Application.WorksheetFunction.Vlookup(Trim(Guncode), .Range(WholeRange), 5, False) 'Locate specific gun type according to QR code number
If Guncode = "" Then
MsgBox "This gun doesn't exist in database!"
Else
MsgBox "The tool number is:" & Retrieve1 & vbCrLf & "The gun type is:" & Retrieve2
End If
End With
End Sub
1. I am not sure what is the reason using Address(True, False) for row number.
This comes from a combination of these two functions. The true/false setting is telling the funciton to use/not use absolute references in the address.
Split ( expression [,delimiter] [,limit] [,compare] )
https://www.techonthenet.com/excel/formulas/split.php
expression.Address (RowAbsolute, ColumnAbsolute, ReferenceStyle, External, RelativeTo)
https://learn.microsoft.com/en-us/office/vba/api/excel.range.address
Shouldn't Cell (1, FinalColumn) stands for the column number?
No, the cells fucntiosn basically returns an intersection/address of rows & column.
Try this for example: debug.Print; thisworkbook.Sheets("Sheet1").Cells(2,2)
You mentioned CSTR doesn't magically transform to letter equivalent so what would it transform to? Could you further elaborate?
This is a data type conversion function. CSTR(666) essentially does this: this 666 becomes this "666"
2. vArr(0). I am confused with what does the parameter 0 stands for in the bracket. Actually this is a general question I always have regarding to parameter specification.
This is an array position refence. The split function returns an array of strings. Since we're using to capture the column label value, we only need to reference the first position.
(3) I tried copy your code and run it but still reminds me error on the same row.
Works fine for me unless there is no returning value, which returns an error which is what I meant by "bomb."
Im trying to use the environ function to only allow certain users to use a document
Here is my issue: it works with one username, not with several usernames....
I know nested loops could be a solution here but I think there is probably an easier way. Reference tables also didn’t work successfully
The current code looks like
If ((IDnumber=“12345”) or (IDnumber=“1234”) or IDnumber=“123”)) then
Msgbox “approved”
Else: msgbox “denied”
Select Case is the appropriate statement to use, here:
Dim strMsg as String
Select Case IDnumber
Case 12345, 1234, 123
strMsg = "Approved"
Case Else
strMsg = "Denied"
End Select
Msgbox strMsg
If your variable IDnumber is a string (in which case, bad choice of variable name!) then use quotes around each item in the list:
Dim strMsg as String
Select Case IDnumber
Case "alpha", "bravo", "charlie"
strMsg = "Approved"
Case Else
strMsg = "Denied"
End Select
Msgbox strMsg
One could argue if using Select Case (as Olly suggests) or If is the better solution.
However, the syntax for the If would be
If IDnumber = "12345" Or IDnumber = "1234" Or IDnumber = "123" Then
MsgBox "approved"
Else
MsgBox "denied"
End if
You have several mistakes in your code snippet:
unbalanced parentheses. In your case, you don't need any parentheses at all. In VBA, (unlike in many other languages), it is not needed to wrap the whole logical term in parentheses. Also, no need to wrap the single or-conditions into parentheses.
As Marcucciboy2 said in a comment, wrong quote characters, use "
The syntax else: MsgBox is valid but not a good style. The : separates two statements, it's better to write this in 2 lines. Anyhow, you need an ending End If statement
The allowed usernames could be passed as an Array, and then check whether the current username is in that array. The valueInArray() does exactly this:
Sub CheckUser()
Dim userNames As Variant
userNames = Array("User1", "User2", "User3")
If valueInArray(Environ("UserName"), userNames) Then
Debug.Print "User Present"
Else
Debug.Print "User Not Present"
End If
End Sub
Public Function valueInArray(myValue As Variant, myArray As Variant) As Boolean
Dim cnt As Long
For cnt = LBound(myArray) To UBound(myArray)
If LCase(CStr(myValue)) = CStr(myArray(cnt)) Then
valueInArray = True
Exit Function
End If
Next cnt
End Function
What is wrong with this line of code? Throws up Run-time error '13', Type mis-match.
Dim mail As Outlook.MailItem
If mail.Subject Like "VEH" & "*" Or "MAT" & "*" Then
Trying to say if the subject of the email starts with "VEH" or "MAT", then do something.
You can simply use VBA LEFT function here:
If UCASE(LEFT(TRIM(mail.Subject), 3)) = "VEH" OR UCASE(LEFT(TRIM(mail.Subject), 3)) = "MAT" Then
'' DO something here
End If
If the emails are from different users then I wouldn't recommend using Like in such a scenario. If it is machine generated with fixed Subject then it makes sense.
Reason: Like/Left is case sensitive
Example:
Sub Sample()
Dim s As String
s = "vehicle"
If s Like "VEH*" Then
MsgBox "Found a match"
Else
MsgBox "didn't find a match"
End If
End Sub
or
Sub Sample()
Dim s As String
s = "vehicle"
If Left(s, 3) = "VEH" Then
MsgBox "Found a match"
Else
MsgBox "didn't find a match"
End If
End Sub
Alternative
For a search which is not case sensitive for example Vehicle, vehicle, VeHiCle, modify what #PareshJ posted.
Sub Sample()
Dim subj As String
subj = " Vehicle Number XYZ"
If UCase(Left(Trim(subj), 3)) = "VEH" Then
MsgBox "Found a match"
Else
MsgBox "didn't find a match"
End If
End Sub
Trim trims the leading and trailing spaces and Ucase converts a string into uppercase.
Edit
If you still want to use Like then you may want to use this
Option Compare Text '<~~ For case insensitive
Sub Sample()
Dim subj As String
subj = " Vehicle Number XYZ"
If Trim(subj) Like "VEH*" Then
MsgBox "Found a match"
Else
MsgBox "didn't find a match"
End If
End Sub
Caution: Option Compare Text will also affect any other comparisons in the code.
The correct syntax for your If statement is:
If (mail.Subject Like "VEH*") Or (mail.Subject Like "MAT*") Then
The brackets are optional (Like operator has higher precedence than Or), but it's easier to read.