I have the following code:
Dim UserID As String = "James"
Dim AccNo As String = "S10001"
Dim err As Boolean = False
If Left(AccNo , 1) = "S" Then
If UserID <> "Alex" Or UserID <> "James" Then
err = True
End If
End If
Why I always get the result err=True? Whats wrong with my code?
I think you maybe wanted And rather than Or, because trivially, a UserID will always not be equal to at least one of two distinctly different values, and so one or other of the comparisons will always be true:
If Left(AccNo , 1) = "S" Then
If UserID <> "Alex" And UserID <> "James" Then
err = True
End If
End If
This is because you are doing two 'not' or 'other than' statements which must always be true, because whatever value you test the other is always true.
Because while UserID is equal to 'James' it is also not equals to 'Alex' hence the condition satisfies and changes the variable to true.
That's the right result.
1st condition: Left(AccNo , 1) = "S" is true, so it enters the if block
2nd condition: (UserID <> "Alex" Or UserID <> "James") -> If either of the two result is true, you code will execute the If block.
If you don't want to enter the condition, just change the OR into AND, meaning that the User should NOT be James NOR should he be Alex
I guess you want to express something like "The user id is neither Alex nor James". This in logic would be not (UserID is Alex or UserId is James). As not (x or y) is the same as not x and not y, this equals UserID is not Alex and UserId is not James, or in VB syntax:
UserID <> "Alex" And UserID <> "James"
As a sidenote, you can make your code look a bit nicer, if you use something like this:
If Not {"A", "B", "C"}.Contains("D") Then
' do something
End If
This replaces
If "D" <> "A" AndAlso "D" <> "B" AndAlso "D" <> "C" Then
' do something
End If
Also - as you might have noticed - VB also knows "AndAlso" and "OrElse" which should in most situations used to replace "And" and "Or". Check this for an explanation: AndAlso vs And
Related
I have 2 separate functions, each one returns its own string value.
I am wanting to check that both return a specific string value and if they do then perform a task.
Example:
If function Apples returns "Apples" and Function Pears () returns "Pears" then do something
I am currently using 2 nested If statements and I want to know if this is the best way to do it.
If Apples() = "Apples" Then
If Pears() = "Pears" Then
"Do something here"
End If
End If
Using ANDALSO, if the first comparison fails, the second comparison is not made:
If String.Compare(Apples(),"Apples", True) = 0 ANDALSO String.Compare(Pears(),"Pears", True) = 0 Then
'Do Something Here
End If
Be careful with string comparisons, the comparison is case sensitive. "Apples" <> "APPLES".
Another version:
If Apples().ToUpper = "APPLES" ANDALSO Pears().ToUpper = "PEARS" Then
'Do Something Here
End If
I'm pretty new to VBA and having issues with a Else statements running even when If conditions are met.
Pretty sure this is due to the If statement being within a For & Next
For iCnt = 1 To Len(Firstname)
If IsNumeric(Mid(Firstname, iCnt, 1)) Then
MsgBox "The Firstname cannot contain Numeric values"
ElseIf Len(Firstname) > 100 Then
MsgBox "The Firstname exceeds the character limit (100)"
Else
Sheet3.Cells(lRow, 2).Value = Me.Firstname.Value
End If
Next iCnt
Please any suggestions how to fix this?
Really you only want the first condition to exist in that FOR loop. The rest of it should be tested afterwards and only if that first condition never trips.
Consider instead:
Dim nameHasNumbers as boolean: nameHasNumbers = False
For iCnt = 1 To Len(Firstname)
If IsNumeric(Mid(Firstname, iCnt, 1)) Then
'number found toggle flag and exit the loop
nameHasNumbers = True
exit For
End If
Next iCnt
'Now alert the user or update the name cell
If nameHasNumbers Then
MsgBox "The Firstname cannot contain Numeric values"
ElseIf Len(Firstname) > 100 Then
MsgBox "The Firstname exceeds the character limit (100)"
Else
Sheet3.Cells(lRow, 2).Value = Me.Firstname.Value
End If
For each letter in the name you are going to get the Else to happen. Need to restructure the whole thing. I would put the checking into a function and then based on that result do your other work. If you need a message to inform the user of the reason for the name being invalid add that to the function. Your function can then do other testing on other conditions without affecting your calling code.
Private Function IsValidName(ByVal value As String) As Boolean
If Len(value) > 100 Then
IsValidName = False
Exit Function
Else
Dim charCounter As Long
For charCounter = 1 To Len(value)
If IsNumeric(Mid(value, charconter, 1)) Then
IsValidName = False
Exit Function
End If
Next
IsValidName = True
End If
End Function
When you want to check whether a string includes a digit, you can compare it to a Like pattern which matches a digit: FirstName Like "*[0-9]*"
That approach is simpler than looping through the string checking whether each character is a digit. And since it does not require the For loop, it should be easier to avoid the logic error in your code sample. (As long as the string length did not exceed 100 characters, it wrote a value to Sheet3.Cells(lRow, 2).Value again for each and every non-numeric character contained in FirstName.)
If FirstName Like "*[0-9]*" Then
MsgBox "The Firstname cannot contain Numeric values"
ElseIf Len(FirstName) > 100 Then
MsgBox "The Firstname exceeds the character limit (100)"
Else
Sheet3.Cells(lRow, 2).Value = Me.FirstName.Value
End If
I'm using the below code to filter a query, however it only returns exact matches. If I want to look at every person with John in their name, how would I change this?
With Me
.Filter = "[Initiator's Name]='John'"
.FilterOn = True
End With
I got it
With Me
.Filter = "[Initiator's Name] LIKE '*John*'"
.FilterOn = True
End With
I have a really long IF AND OR formula that I'm trying to convert to VBA so it's quicker.
=IF(OR(H10<>"GL402",H10<>"GL412",H10<>"GL422",H10<>"GL432",H10<>"GL442",H10<>"GL452",H10<>"GL492",
H10<>"GL480",H10<>"GL370",H10<>"GL380",H10<>"GL710")*AND(OR(D10<>3,D10<>9,D10<>10),E10<>"ASX",
F10<>"AUD"),"F126",(IF(OR(H2="GL402",H2="GL412",H2="GL422",H2="GL432",H2="GL442",H2="GL452",H2="GL492")*
AND(OR(D2<>"3",D2<>"9",D2<>"10"),E2="ASX",F2="AUD"),"D111",.......))
I thought this should look like:
IF range("H10").Value <>""GL402"" or ""GL412"" or ""GL422"" or ""GL432"" or ""GL442"" _
or ""GL452"" or ""GL492"" or ""GL480"" or ""GL370"" or ""GL380"" or ""GL710"" AND _
range("D10").Value <>3 or 9 or 10 and range("E10").Value <>""ASX"" and _
range("F10").Value <>""AUD""
then
range("I10").Value = ""F126""
elseif
Range("H2").Value = ""GL402"" Or ""GL412"" Or ""GL422"" Or ""GL432"" Or ""GL442"" Or ""GL452"" Or ""GL492"" _
And Range("D2").Value <> 3 Or 9 Or 10 And Range("E2").Value = ""ASX"" And Range("F2").Value = ""AUD""
then
Range("I2").Value = ""D111""
elseif
another lengthy conditions with ANDs and ORs
plus I was hoping to loop this so it applies this whole IF formula until the value of cell A (whichever row) is blank.
I sort of know the loop should be
Do .........
next (with something like A1 + 1)
until A1 + 1 = ""
loop
any help appreciated!
The first rule of good code is that it should be clear - easy to read and debug. Only afterwards do you try to make it "fast". Converting your current expression to VBA may give a speed advantage but you still don't meet the first test...
You can make things cleaner with an expression like this (you can put this right in your spreadsheet):
=ISERROR(MATCH(H10,{"GL402","GL412","GL422","GL432","GL442","GL452","GL492","GL480","GL370","GL380","GL710"},0))
This will evaluate to "true" if the the value in H10 does not match any of the values in the array.
When you have a lot of or conditions in parallel, you can basically stop when the first condition is true.
An expression like that can be written in VBA as follows:
Sub test()
Dim matchStrings
Dim match1, match2
matchStrings = Array("GL402", "GL412", "GL422", "GL432", "GL442", "GL452", "GL492", "GL480", "GL370", "GL380", "GL710")
firstPart = Application.Match(Range("H10"), matchStrings, 0)
If IsError(firstPart) Then
MsgBox "no match found"
Else
match1 = true
MsgBox "match found at index " & firstPart
End If
End Sub
You can repeat similar code with other expressions, building match2, match3, etc - then combining with all the And and Or that you would like - for example
If match1 And (match2 Or match3) Then
... do something
Else
... do something else
End If
This won't work as expected:
If x = 1 Or 2 Or 3 Then
MsgBox "x is either 1, 2, or 3"
End If
because 2 and 3 aren't boolean (true/false) conditions (at least not the way you expect them to be).
The proper syntax is:
If x = 1 Or x = 2 Or x = 3 Then
MsgBox "x is either 1, 2, or 3"
End If
This is only a partial answer that nevertheless does address one of the many issues in your code.
say I wanted the following code:
Sub X
If TextBox1.Text = "Value" then
' Do something
ElseIf TextBox1.Text = "Value1" then
' Also do some other code
End IF
End Sub
How would I do this?
I would like the program to check something first, and if that is true then check something else, and if that is true, also execute that code.
Are you looking for AndAlso?
If TextBox1.Text = "Value" AndAlso TextBox2.Text = "Value1" Then
....
End If
The AndAlso operator performs a logical operation between the two sides of the expression. It evaluates the first condition and if this condition is false it stop further processing (without evaluating the second expression). Only if both conditions are true the code inside the if is executed. This behavior is called short-circuiting evaluation
However, the code in your question cannot be evaluated as true in both conditions for the same TextBox1
If condition1
then
if condition2
then
// do something
end if
end if
If the example in your code is valid, equals value1 then equals value2, do you mean you want if either, because it cannot be both equal?
In this case you can use OR.
Instead of else-if, do:
If TextBox1.Text = "Value" then
' Do something
end if
If TextBox1.Text = "Value1" then
' Also do some other code
End IF
or:
If TextBox1.Text = "Value" then
' Do something
If TextBox1.Text = "Value1" then
' Also do some other code
End IF
end if
Depending on whether you want to execute B only if A is also true.