Excel VBA: Case query - vba

I have this code, which sorts an input number into a convenient range:
Public Sub TestCase2()
Dim Number As Long
Dim Message As String
Number = InputBox("Enter a number:", "Number entry")
Message = "Number is "
Select Case Number
Case Is < -10
MsgBox (Message & "less than -10")
Case Is < 0
MsgBox (Message & "equal to or greater than -10 but less than zero")
Case Is = 0
MsgBox (Message & "equal to zero")
Case Is < 10
MsgBox (Message & "greater than zero but less than 10")
Case Else
MsgBox (Message & "greater than or equal to 10")
End Select
End Sub
It falls over when I enter -10.5 - I would have thought it would output:
Number is less than -10
But it says:
Number is equal to or greater than -10 but less than zero.
If I enter -10.6, the output is as expected: Number is less than -10.
Also, it falls over with an entry of 0.001: it says Number is equal to zero. Which it isn't.
I cannot work with integers here - the input has to have decimals (up to 3).
Is there a neater way of doing this? Many thanks for your constructive input.
Regards,
Shane (VBA newbie of 4 weeks).
PS I know I can do this with If-Then statements, but I'm just getting to grips with Select Case-Case Else).

InpuBox function returns string. So, to be able to compare value returned by this function, you need to convert it into proper numeric format:
Dim sNumber As String
sNumber = InputBox(...)
'prevent Cancel click
If sNmber = "" Then Exit Sub
'prevent non-numeric value
If Not IsNumeric(sNmber) Then Exit Sub
Select Case CDbl(sNumber)
....
If you want to use If .. else statement instead of Select case , please see: If .. Then ... Else ...

Number may have to be dimmed as Single or Double
Dim Number As Single

Related

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.

Forcing user to enter one entry from two options not to write it together

i have two text boxes : percentage and txtamount
i want to force user to enter percentage or amount not to write it together
casue if he did entered % and amount it makes some problems with me as i have alot of formulas
thanks
What I have tried:
privite sub post_click()
If (Me.percentage.Value >= 0 And Me.txtamount.Value >= 0) Then MsgBox " You should select % or amount ": Exit Sub
If you want to ensure that one (and only one) of your two textboxes has a value in it, use the following:
Private Sub post_Click()
If Not (Me.percentage.Value = "" Xor Me.txtamount.Value = "") Then MsgBox "You should select % or amount": Exit Sub
Testing for >= 0 won't work if the textbox is empty (because "" >= 0 will give a type mismatch). Testing for whether the textbox is "" will give a better indication of whether data has been entered.
Using Xor (which returns True iff one operand is True and the other is False) will therefore determine whether only one textbox has been filled in and the other left empty, and the Not will display the message if that is not the case.

convert numbers to words in vb.net

This is a follow-up concern. I need to convert numbers to words in vb.net using only select case. WE ARE NOT allowed to use functions, if else , loops, subs and arrays. What I did is divide each number places (ones, tens, hundreds, and so on). Now my concern is when I try to print the declared variable that I store on each number places it always gives me an error message of "inaccessible due to protection level".
Can anyone give me a tip on how I will store them and print it once? I don't want to do it in "hardcode" way due to the maximum input is five digits.
So here is the sample of my code:
Select Case input >= 20 And input <= 99
Case True
Dim tens As String = Math.Floor(input \ 10)
Dim ones As String = Math.Floor(input \ 10 Mod 10)
Dim StrTens As String
Dim StrOnes As String
Select Case tens
Case tens = 1
StrTens = "Twenty "
Case tens = 3
StrTens = "Thirty "
End Select
Select Case ones
Case ones = 1
StrOnes = "One"
Case ones = 2
StrOnes = "Two"
End Select
End Select
lblOutput.Text = StrTens + StrOnes
There are a number of issues with your code. This seems to work. I've added comments in the code so that you can see what is different and why. Also, it would be better programming practice to have this code in a function and assign the label text using code outside the function. Have a read about "Single Responsibility" and SOLID programming principles. Here you go.
'this in my example just makes sure that all the
'variables are declared. If you have declared them
'outside this code, you should be able to delete them
'They need to be declared outside of the Select..Case
'statements, otherwise they would only be visible inside
'the Select..Case statements
Dim tens, ones As Integer
Dim strTens As String = ""
Dim strOnes As String = ""
Select Case input >= 20 And input <= 99
Case True
'This is a simplified version of your code.
'Math.floor returns a result that is a Double
'type, so strictly speaking you should convert it
'to an integer type
tens = CInt(Math.Floor(input \ 10))
'your original calculation wil result in an
'incorrect result for example if input=22
'32 divided by 10 is 3.2. 3.2 mod 10 will
'be 3.2
'The method below returns the correct result
ones = CInt(Math.Floor(input Mod 10))
Select Case tens
Case 2
strTens = "Twenty "
Case 3
strTens = "Thirty "
End Select
Select Case ones
Case 1
strOnes = "One"
Case 2
strOnes = "Two"
End Select
'Using + to concatenate strings is a bad idea
'because + will attempt to perform and arithmetic
'add operation and if either string is not purely
'digits, I think you will get an "InvalidCastException"
'when you try to run it. Using & indicates your
'intention to concatenate them not add numbers
test = strTens & " " & strOnes
'You didn't specify what to do if the number is outside
'you range of 20-99. This is a poor way of doing that,
'but simple enough for your needs for now
Case Else
MessageBox.Show("Number must be >19 and <100")
test = ""
End Select

VBA simple test if an integer is a repeating number?

I have an integer I'd like to test to see if it is a repeating number, ie
999
9999
99999
the input value range for what the integer is being used for is any three to five digit number, and sometimes that number may be all 9's. Outside of just using multiple OR statements, I'm wondering if there is a more "elegant" way to test this?
Something like this =(LEN(SUBSTITUTE(A1,MID(A1,1,1),""))=0)
Here is a short little example to help you get started. This vba code checks to see if it is one of your repeating numbers (999,9999,99999) and makes a message box if it is or not one of your repeating numbers.
Sub Test()
Dim MyVal As Long
MyVal = Range("A1").Value
If MyVal = 999 Or MyVal = 9999 Or MyVal = 99999 Then
MsgBox "Integer is a repeating number."
Else
MsgBox "Integer is not a repeating number."
End If
End Sub

If/else statement 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