If email subject line starts with certain values then do something - excel

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.

Related

Run time error '1004' Application defined or object defined error on Vlookup function

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."

VBA - Returning Range or Number from Applilcation.InputBox

I am using Applilcation.InputBox to get a number from the user. Further in the code I am multipying a range of cells with that number.
My problem is that I want to know if the number was written manually or chosen by selecting a cell in the worksheet (that means if the user has written „123“ then „123“ and if he has selected a range then return $A$1).
Code:
Dim output As Variant
Set output = Application.InputBox("Enter Number", "Number for multyplying")
Any advice, please?
I don't think you can do this. Either you set the type to 8, and then you can't enter numbers, or you set it to 1 and then you can't enter references. If you combine it to 9, you still have the problem with Set or no Set.
' Works for ranges
Set Output = Application.InputBox("Enter Number", "Number for multyplying", , , , , , 8)
' Works for literals
Output = Application.InputBox("Enter Number", "Number for multyplying", , , , , , 1)
' Could have worked for both, but it doesn't
Set Output = Application.InputBox("Enter Number", "Number for multyplying", , , , , , 9)
I think the cleanest way to solve this is to implement a UserForm with a RefEdit control.
So, with Application.InputBox I wasn't able to achieve the desired functionality, allthough I still think it's possible somehow... :-)
This is what I came up with (using a UserForm with RefEdit and other tools):
Pay no attention to the picture in the background. I was just trying out stuff... :-) Allthough, I quite like it after all :-)
And this is the code for the commandButton:
(ref_Input being the RefEdit, txb_number the TextBox)
Public gNmr As Variant
Private Sub cmd_OK_Click()
Dim adr As String
If ref_Input.Value <> vbNullString And txb_number.Value <> vbNullString Then
MsgBox "Choose just one option, please.", , "Wrong input"
Exit Sub
Else
If ref_Input.Value = vbNullString And txb_number.Value = vbNullString Then
MsgBox "No input, please try again.", , "Wrong input"
Exit Sub
Else
If txb_number.Value = vbNullString Then
adr = ref_Input.Value
gNmr = adr
Else
If ref_Input.Value = vbNullString Then
gNmr = txb_number.Value
End If
End If
End If
End If
Unload Me
End Sub

Environ function with several users

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

VBA - Check if "Comma" exists in a string or not

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

Handling non integer in inputbox in VBA

I have a variable called "need" that is defined as an integer. An input box come up and prompts the user. If they type an integer it displays Msgbox "Got your number". If I type a string I get Runtime error '13': type mismatch. I thought if I just used an Else statement, it would say try again. It is not doing that though. Do I need error handling in the Else statement? And if so, what would the line(s) be?
Sub gadgetmanuf()
Dim need As Integer
'Dim rawneed As Single
'Dim rawavailable As Single
need = InputBox("How many gadgets are needed?", "Insert a number")
If TypeName(need) = "Integer" Then
MsgBox ("Got your number")
Else
MsgBox ("Try again")
End If
End Sub
Using an Application.InputBox with type 1 forces the user to enter a number (provides its own error message for text, ranges etc). So all you need to handle is the Cancel option, ie
The code below uses a variant to handle this, as using Cancel with an Integer or Long gives 0 - which could be a valid entry.
Sub TaylorWalker()
redo:
vStr = Application.InputBox("How many gadgets are needed?", "Enter a number", , , , , , Type:=1)
If vStr = False Then GoTo redo
End Sub
longer option
Test that the entered variable is greater than 0
Sub EddieBetts()
Dim StrPrompt As String
Dim lngNum As Long
StrPrompt = "How many gadgets are needed?"
redo:
lngNum = Application.InputBox(StrPrompt, "Enter an integer number (numbers will be rounded)", , , , , , Type:=1)
If lngNum < 1 Then
StrPrompt = "How many gadgets are needed - this must be a postive integer"
GoTo redo
End If
MsgBox "User entered " & lngNum
End Sub
In your example 'need' is an integer data type so it will always be an integer.
Have a look at this:
Sub test()
x = Range("A1").Value
If Int(x) / x = 1 Then
MsgBox "Value is an Integer"
Else
MsgBox "Value is not an Integer"
End If
End Sub
or Assuming A1 has the number, put, in any other cell, the formula:
=IF(INT(A1)=A1,"True","False")

Resources