If/else statement VB.Net - vb.net

If txtNum1.Text <= 0 Or txtNum2.Text <= 0 Then
lblResult.Text = "Result Error: Enter in a number graeter than zero"
End If
I am new to programming. I am trying to create an if/else statement so that if the number in either text box is less than or equal to 0 it will display an error message and not crash.

You have to Parse the number in the .Text property as an integer.
so your If statement would be something like
If Int32.Parse(txtNum1.Text) <= 0 ....
if you plan on reusing that value multiple times in your code, you can extract it in a variable.
Also, as pointed out in the comments, you should check for invalid numbers, you can do so, with Int32.TryParse(value, number). So then, if the TryParse(..) method returns false, you can handle the case.
To know exactly how this method works, you can read this
But to make it quick value is the string you want to parse and number is the integer value that is parsed out of the string. The method itself returns a boolean (true if it was successfully parse, and false otherwise)

Use proper conversion from string to numbers
Dim res1 As Integer
Dim res2 as Integer
if Not Int.TryParse(txtNum1.Text, res1) then
lblResult.Text = "Enter a valid first number "
return
End If
if Not Int.TryParse(txtNum2.Text, res2) then
lblResult.Text = "Enter a valid second number "
return
End If
If res1 <= 0 OrElse res2 <= 0 Then
lblResult.Text = "Result Error: Enter numbers greater than zero"
End If
You need to convert the user input to a numeric value. The Text property of a textbox is a string not a number. And if you want to convert it you should be prepared to receive bad inputs (like a non numeric value).
The best approach is to use Int.TryParse that try to convert the value typed by your user in a number and if it fails returns false. If successful the converted number will be found in the second argument.
Notice also that you should use OrElse instead of Or because the former use short-circuit evaluation
I wish to warn you about another pitfall that seems to be evident from the error message. The VB compiler tried to help you converting the two strings in numbers. This is very bad from my point of view. You should take the responsability to handle this kind of conversions disabling the automatic conversion of the compiler. Go to the properties of your project, page Compile and set the Option Strict to ON. In this way the compiler would stop this automatic conversion and signal as error the textBox1.Text <= 0

something like this would be better,
you check if it is a int then check if it is zero or under
Dim value1, value2 As Integer
If not Integer.TryParse(txtNum1.text, value1) orelse value1 <= 0 OrElse not Integer.TryParse(txtNum2.text, value2) orelse value2 <= 0 Then
lblResult.Text = "Result Error: Enter in a number graeter than zero"
End If

your comparison won't work normally, you are not using the same types (string vs integer)
i'd rather use integer.tryParse
so the code becomes something like :
dim n1 as integer
dim n2 as integer
if integer.tryparse(txtNum1.Text,n1) and integer.tryparse(txtnum2.text,n2) then
If n1 <= 0 Or n2 <= 0 Then
lblResult.Text = "Result Error: Enter in a number graeter than zero"
End If
else
lblResult.Text = "please input numbers"
end if

Related

Variant and if statement - VBA [duplicate]

I have trouble comparing 2 double in Excel VBA
suppose that I have the following code
Dim a as double
Dim b as double
a = 0.15
b = 0.01
After a few manipulations on b, b is now equal to 0.6
however the imprecision related to the double data type gives me headache because
if a = b then
//this will never trigger
end if
Do you know how I can remove the trailing imprecision on the double type?
You can't compare floating point values for equality. See this article on "Comparing floating point numbers" for a discussion of how to handle the intrinsic error.
It isn't as simple as comparing to a constant error margin unless you know for sure what the absolute range of the floats is beforehand.
if you are going to do this....
Dim a as double
Dim b as double
a = 0.15
b = 0.01
you need to add the round function in your IF statement like this...
If Round(a,2) = Round(b,2) Then
//code inside block will now trigger.
End If
See also here for additional Microsoft reference.
It is never wise to compare doubles on equality.
Some decimal values map to several floating point representations. So one 0.6 is not always equal to the other 0.6.
If we subtract one from the other, we probably get something like 0.00000000051.
We can now define equality as having a difference smaller that a certain error margin.
Here is a simple function I wrote:
Function dblCheckTheSame(number1 As Double, number2 As Double, Optional Digits As Integer = 12) As Boolean
If (number1 - number2) ^ 2 < (10 ^ -Digits) ^ 2 Then
dblCheckTheSame = True
Else
dblCheckTheSame = False
End If
End Function
Call it with:
MsgBox dblCheckTheSame(1.2345, 1.23456789)
MsgBox dblCheckTheSame(1.2345, 1.23456789, 4)
MsgBox dblCheckTheSame(1.2345678900001, 1.2345678900002)
MsgBox dblCheckTheSame(1.2345678900001, 1.2345678900002, 14)
As has been pointed out, many decimal numbers cannot be represented precisely as traditional floating-point types. Depending on the nature of your problem space, you may be better off using the Decimal VBA type which can represent decimal numbers (base 10) with perfect precision up to a certain decimal point. This is often done for representing money for example where 2-digit decimal precision is often desired.
Dim a as Decimal
Dim b as Decimal
a = 0.15
b = 0.01
Late answer but I'm surprised a solution hasn't been posted that addresses the concerns outlined in the article linked in the (currently) accepted answer, namely that:
Rounding checks equality with absolute tolerance (e.g. 0.0001 units if rounded to 4d.p.) which is rubbish when comparing different values on multiple orders of magnitude (so not just comparing to 0)
Relative tolerance that scales with one of the numbers being compared meanwhile is not mentioned in the current answers, but performs well on non-zero comparisons (however will be bad at comparing to zero as the scaling blows up around then).
To solve this, I've taken inspiration from Python: PEP 485 -- A Function for testing approximate equality to implement the following (in a standard module):
Code
'#NoIndent: Don't want to lose our description annotations
'#Folder("Tests.Utils")
Option Explicit
Option Private Module
'Based on Python's math.isclose https://github.com/python/cpython/blob/17f94e28882e1e2b331ace93f42e8615383dee59/Modules/mathmodule.c#L2962-L3003
'math.isclose -> boolean
' a: double
' b: double
' relTol: double = 1e-09
' maximum difference for being considered "close", relative to the
' magnitude of the input values
' absTol: double = 0.0
' maximum difference for being considered "close", regardless of the
' magnitude of the input values
'Determine whether two floating point numbers are close in value.
'Return True if a is close in value to b, and False otherwise.
'For the values to be considered close, the difference between them
'must be smaller than at least one of the tolerances.
'-inf, inf and NaN behave similarly to the IEEE 754 Standard. That
'is, NaN is not close to anything, even itself. inf and -inf are
'only close to themselves.
'#Description("Determine whether two floating point numbers are close in value, accounting for special values in IEEE 754")
Public Function IsClose(ByVal a As Double, ByVal b As Double, _
Optional ByVal relTol As Double = 0.000000001, _
Optional ByVal absTol As Double = 0 _
) As Boolean
If relTol < 0# Or absTol < 0# Then
Err.Raise 5, Description:="tolerances must be non-negative"
ElseIf a = b Then
'Short circuit exact equality -- needed to catch two infinities of
' the same sign. And perhaps speeds things up a bit sometimes.
IsClose = True
ElseIf IsInfinity(a) Or IsInfinity(b) Then
'This catches the case of two infinities of opposite sign, or
' one infinity and one finite number. Two infinities of opposite
' sign would otherwise have an infinite relative tolerance.
'Two infinities of the same sign are caught by the equality check
' above.
IsClose = False
Else
'Now do the regular computation on finite arguments. Here an
' infinite tolerance will always result in the function returning True,
' since an infinite difference will be <= to the infinite tolerance.
'This is to supress overflow errors as we deal with infinity.
'NaN has already been filtered out in the equality checks earlier.
On Error Resume Next
Dim diff As Double: diff = Abs(b - a)
If diff <= absTol Then
IsClose = True
ElseIf diff <= CDbl(Abs(relTol * b)) Then
IsClose = True
ElseIf diff <= CDbl(Abs(relTol * a)) Then
IsClose = True
End If
On Error GoTo 0
End If
End Function
'#Description "Checks if Number is IEEE754 +/- inf, won't raise an error"
Public IsInfinity(ByVal Number As Double) As Boolean
On Error Resume Next 'in case of NaN
IsInfinity = Abs(Number) = PosInf
On Error GoTo 0
End Function
'#Description "IEEE754 -inf"
Public Property Get NegInf() As Double
On Error Resume Next
NegInf = -1 / 0
On Error GoTo 0
End Property
'#Description "IEEE754 +inf"
Public Property Get PosInf() As Double
On Error Resume Next
PosInf = 1 / 0
On Error GoTo 0
End Property
'#Description "IEEE754 signaling NaN (sNaN)"
Public Property Get NaN() As Double
On Error Resume Next
NaN = 0 / 0
On Error GoTo 0
End Property
'#Description "IEEE754 quiet NaN (qNaN)"
Public Property Get QNaN() As Double
QNaN = -NaN
End Property
Updated to incorporate great feedback from Cristian Buse
Examples
The IsClose function can be used to check for absolute difference:
assert(IsClose(0, 0.0001233, absTol:= 0.001)) 'same to 3 d.p.?
... or relative difference:
assert(IsClose(1234.5, 1234.6, relTol:= 0.0001)) '0.01% relative difference?
... but generally you specify both and if either tolerance is met then the numbers are considered close. It has special handling of +-infinity which are only close to themselves, and NaN which is close to nothing (see the PEP for full justification, or my Code Review post where I'd love feedback on this code :)
The Currency data type may be a good alternative. It handles relatively large numbers with fixed four digit precision.
Work-a-round??
Not sure if this will answer all scenarios, but I ran into a problem comparing rounded double values in VBA. When I compared to numbers that appeared to be identical after rounding, VBA would trigger false in an if-then compare statement.
My fix was to run two conversions, first double to string, then string to double, and then do the compare.
Simulated Example
I did not record the exact numbers that caused the error mentioned in this post, and the amounts in my example do not trigger the problem currently and are intended to represent the type of issue.
Sub Test_Rounded_Numbers()
Dim Num1 As Double
Dim Num2 As Double
Let Num1 = 123.123456789
Let Num2 = 123.123467891
Let Num1 = Round(Num1, 4) '123.1235
Let Num2 = Round(Num2, 4) '123.1235
If Num1 = Num2 Then
MsgBox "Correct Match, " & Num1 & " does equal " & Num2
Else
MsgBox "Inccorrect Match, " & Num1 & " does not equal " & Num2
End If
'Here it would say that "Inccorrect Match, 123.1235 does not equal 123.1235."
End Sub
Sub Fixed_Double_Value_Type_Compare_Issue()
Dim Num1 As Double
Dim Num2 As Double
Let Num1 = 123.123456789
Let Num2 = 123.123467891
Let Num1 = Round(Num1, 4) '123.1235
Let Num2 = Round(Num2, 4) '123.1235
'Add CDbl(CStr(Double_Value))
'By doing this step the numbers
'would trigger if they matched
'100% of the time
If CDbl(CStr(Num1)) = CDbl(CStr(Num2)) Then
MsgBox "Correct Match"
Else
MsgBox "Inccorrect Match"
End If
'Now it says Here it would say that "Correct Match, 123.1235 does equal 123.1235."
End Sub
Depending on your situation and your data, and if you're happy with the level of precision shown by default, you can try comparing the string conversions of the numbers as a very simple coding solution:
if cstr(a) = cstr(b)
This will include as much precision as would be displayed by default, which is generally sufficient to consider the numbers equal.
This would be inefficient for very large data sets, but for me was useful when reconciling imported data which was identical but was not matching after storing the data in VBA Arrays.
Try to use Single values if possible.
Conversion to Double values generates random errors.
Public Sub Test()
Dim D01 As Double
Dim D02 As Double
Dim S01 As Single
Dim S02 As Single
S01 = 45.678 / 12
S02 = 45.678
D01 = S01
D02 = S02
Debug.Print S01 * 12
Debug.Print S02
Debug.Print D01 * 12
Debug.Print D02
End Sub
45,678
45,678
45,67799949646
45,6780014038086

IsNumeric statement and a range

Hey everyone I am working on an assignment where i have to validate the user input data. When asking my instructors if i can use a IsNumeric to validate a range between two numbers he just said yes and did not show me how.
Now I know you can validate using if statements , and i have several doing so with a basic:
if hours < 0 then
Messagebox("Please enter a value greater than 0" "Input Value to
low" messagebox.buttons retry/cancel) ''something like that
Elseif hours > 23 then
Messagebox( "please enter a value less than 23" "Input Value to
high" messagebox.buttons retry/cancel)
End if
I even asked him if i can use a AND in the if statement to range the data. Again yes with no example
Example that i had in mind
If hours < 0 AND hours > 23 then
'' continue processing
Else
Messagebox("Please enter a Value between 0 and 23" "Input
value
out of range" messagebox.buttons retry/cancel)
End if
In response to your example you can try this:
If isnumeric(hours) then
If hours < 0 AND hours > 23 then
'' continue processing
Else
MessageBox.Show("Input value out of range",
"Please enter a Value between 0 and 23",
MessageBoxButtons.RetryCancel)
End if
End if
IsNumeric() is old... modern practice would tend to use Integer.TryParse() or Double.TryParse(), depending on what kind of value you need. You can also use CInt() or Convert.ToInt32(), but when you know you start with a string, parsing is the best choice.
But what concerns me is you should also have Option Strict turned on, or at least Option Infer. Anything else is really poor practice. With that in mind, look at this code:
Dim hours As String = GetSomeValueFromUser()
If IsNumeric(hours) Then
If hours < 0 Or hours > 23 Then 'a value can never be both negative *and* greater than 24
'...
End
End If
In any sensible project, that should be a compiler error, because it uses a string value (hours) as if it's a number. It doesn't matter that you checked with IsNumeric() first. If you're using Option Strict, as you should be, that's still an error.
This is much better practice:
Dim hours As String = GetSomeValueFromUser()
Dim hrs As Integer
If Integer.TryParse(hours, hrs) AndAlso hrs>= 0 AndAlso hrs <= 23 Then
'code here
Else
MessageBox.Show("Please enter a Value between 0 and 23" "Input value out of range", MessageBoxButtons.RetryCancel)
End If
One additional thing here: NEVER declare a variable for Function without an explicit type known to the compiler. Option Infer can muddy the waters there somewhat, but generally the type of a variable should always be known and fixed.

Val() Not working correctly or not how it should

I am trying to get a "x" amount from the inputbox and use that value for value changing and the math does something weird and doesn't work correctly.
Dim infantry As Integer
infantry = InputBox("How many do you want to attack with?", "Choose how many:", , ,)
frmMainGame.lblHPAI.Text = (Val(frmMainGame.lblHPAI.Text) - infantry * 2).ToString("N0")
Before
Result
The inputted value was 1
Inputbox() returns a string. You need to convert it to an integer value before you assign it to infantry. Also this function supports overloads so you don't have to include the arguments you don't plan to use.
infantry = CInt(InputBox("How many do you want to attack with?", "Choose how many:"))
This will return an error however if the value entered is non numeric. You would need to use a try/catch or preferably validate the result before using it:
Dim infantry As Integer
Dim Result As String = InputBox("How many do you want to attack with?", "Choose how many:")
If IsNumeric(Result) Then infantry = CInt(Result) Else MsgBox("Enter a numeric value", MsgBoxStyle.Critical)
We use Integer.TryParse to get the inputted value (TryParse because we don't have control about what can be that value)
If the parsing is successful we retrieve the label value (using Parse because that value is under our control so should always be a valid int)
Finally we make the calculation and assign the label it's representation.
If the parsing fail we should handle that (error message, looping to get a new value, etc.)
For (possibly both) parsing you should take care of formatting and culture issues which will dictate what format is valid or not.
Dim input = InputBox("How many do you want to attack with?", "Choose how many:")
Dim infantry As Integer
If Integer.TryParse (input, infantry) Then
Dim hpai = Integer.Parse (frmMainGame.lblHPAI.Text, NumberStyles.AllowThousands, CultureInfo.InvariantCulture)
frmMainGame.lblHPAI.Text = (hpai - infantry * 2).ToString("N0")
Else
' handle not an int inputted case
End If

Convert Textbox value to Integer

I have the following Integer variables
Dim sMaxAmount As Integer
Dim sMinAmount As Integer
I am trying to compare them with a TextBox field.
If (Convert.ToInt32(txtTransactionAmount) < sMinAmount And Convert.ToInt32(txtTransactionAmount) > sMaxAmount) Then
Although I am converting it to Integer I get exception
Unable to cast object of type 'System.Web.UI.WebControls.TextBox' to
type 'System.IConvertible'.
What am I doing wrong?
Typo: use txtTransactionAmount.Text instead of txtTransactionAmount
If (Convert.ToInt32(txtTransactionAmount.Text) < sMinAmount AndAlso Convert.ToInt32(txtTransactionAmount.Text) > sMaxAmount)
Val(TextBox.Text) will convert the value of a TextBox to an Integer.
txtTotal.text= Val(txtPrice.text) * Val(txtQuantity.text)```
In addition to not using the Text property to get the string contained in the TextBox, there are two other problems with your code.
You are not validating the contents of the TextBox. If the user enters something that can't be converted to an integer, an exception will be thrown.
The test you are doing doesn't make sense given the names of the variables. The value in the TextBox can't be both less than the minimum and more than the maximum.
The following code uses Integer.TryParse to validate the contents of the TextBox and convert it to an Integer. It also checks that the value in greater than or equal to sMinAmount and less than or equal to sMaxAmount.
Dim amount As Integer
If Integer.TryParse(txtTransactionAmount.Text, amount) _
AndAlso amount >= sMinAmount AndAlso aamount <= sMaxAmount Then
'The Integer called "amount" now contains a value between sMinAmount and sMinAmount
End If

VB determining values within a string

I am looking for assistance with my program. I have a user enter 6 digits; of these the input must be alpha-numeric. I have already done the TryParse method for the numbers, but I am looking for validation that the string contains an alpha.
I am aware you must use ASC but am unsure both on how to develop a range say Asc((Chr(65) <= Chr(90))) (between A-Z) and also to say (IF my input contains any of these values within the 6 characters, to return true. I keep getting an overload resolution and wish to know how to properly code so the variables are accurate.
This is a great place to use a regular expression
Dim input = ...
If Regex.IsMatch(input, "^\w+$") AndAlso input.Length = 6 Then
' It's a match
Else
' It's not a match
End If
This will match any string which consists only of letters that has length equal to 6
You can iterate through each char and check if it's a letter. If so, set a flag to true.
Dim containsAlpha Boolean = False
For i As Integer = 0 To input.Length - 1
If Char.IsLetter(input(i)) Then
containsAlpha = True
Exit For
End If
Next
Char.IsLetter will match Unicode alphabetic letters, so not just Latin A-Z (which may or may not be what you actually want).