ElseIf statement skipped when it shouldn't be with "or" - vba

I'm building a little program to help out with some data imports and for our techs when out on sites.
The bit I'm struggling with is the bp check, see code below:
Private Sub bphg_afterupdate()
'blood pressure values
'below 100/60 - low
'120/70 - normal
'140/90 - high, gp review
'180/100 - high, cut off for fitness for driving
'200/100 - high, cut off for driving/spiro
'230/120 - urgent review required
If bpmm <= 100 Or bphg <= 60 Then
bpcomment.Value = "LOW! - Seek Advice"
ElseIf bpmm < 140 Or bphg < 90 Then
bpcomment.Value = "Normal BP"
ElseIf bpmm < 180 Or bphg < 100 Then
bpcomment.Value = "High! - GP Review"
ElseIf bpmm < 200 Then
bpcomment.Value = "High! - Temp restriction to driving MPE/FLT"
ElseIf bpmm < 230 Or bphg < 120 Then
bpcomment.Value = "High! - To high for Spiro & Temp Driving Resitricion MPE/FLT"
Else
bpcomment.Value = "URGENT! - Review required"
End If
End Sub
What it's doing is finding the first value that fits in either the values specified and then stopping. It should be continuing to check other criteria.
So basically with blood pressure, out of the 2 figures your doctor gives you, either can determine if your bp is ok or not. So when we enter a bp into the form say 200/80 (you would probably never get this but I'm being through), it would find that the first figure is high and the second is normal. My script however is finding the second figure being normal first without checking the first figure, so it just displays "normal" when in fact it's "high".

Select Case would be a better way to deal with the blood pressure issues:
Option Explicit
Public Sub TestMe()
Dim bpmm As Long
Dim bphg As Long
bpmm = 100 'assign these two somehow. E.g.-> bpmm = ActiveSheet.Range("A1")
bphg = 100
Select Case True
Case bpmm <= 100 Or bphg <= 60
Debug.Print "LOW! - Seek Advice"
Case bpmm < 140 Or bphg < 90
Debug.Print "Normal BP"
Case bpmm < 180 Or bphg < 100
Debug.Print "High!"
Case Else
Debug.Print "URGENT! - Review required"
End Select
End Sub
Instead of Debug.Print, you may put your business logic there. Just make sure that you order the conditions correctly - if the first condition is evaluated to TRUE, the check does not go further.
There is a tiny performance advantage of Select Case - Which way is faster? If elseif or select case
Edit: If your logic is, that all the criteria should be checked separately and independently, then take a look at this:
Public Sub TestMe()
Dim bpmm As Long
Dim bphg As Long
bpmm = 100 'assign these two somehow. E.g.-> bpmm = ActiveSheet.Range("A1")
bphg = 100
If bpmm <= 100 Or bphg <= 60 Then
Debug.Print "LOW! - Seek Advice"
End If
If bpmm < 140 Or bphg < 90 Then
Debug.Print "Normal BP"
End If
If bpmm < 180 Or bphg < 100 Then
Debug.Print "High!"
End If
End Sub

From your description, it looks like you want to return the result of the highest one of the two criteria. In this case, you will need to reverse the order of the checks:
If bpmm >= 230 Or bphg >= 120 Then
bpcomment.Value = "URGENT! - Review required"
ElseIf bpmm >= 200 Then
bpcomment.Value = "High! - To high for Spiro & Temp Driving Resitricion MPE/FLT"
ElseIf bpmm >= 180 Or bphg >= 100 Then
bpcomment.Value = "High! - Temp restriction to driving MPE/FLT"
ElseIf bpmm >= 140 Or bphg >= 90 Then
bpcomment.Value = "High! - GP Review"
ElseIf bpmm >= 120 Or bphg >= 70 Then
bpcomment.Value = "Normal BP"
Else
bpcomment.Value = "LOW! - Seek Advice"
End If
However, it's not clear from the instructions (that you have at the top of your function) what to do in the case it is between 100/60 and 120/70. The code above considers it LOW. If you want to consider it NORMAL instead, then change the last ElseIf from:
ElseIf bpmm >= 120 Or bphg >= 70 Then
to:
ElseIf bpmm >= 100 Or bphg >= 60 Then

Related

How to find federal taxes based on salary ranges

I'm designing a software that does basic payroll for a school project. I'm stuck on this one part where I have to figure out what the federal tax will be based on the employee salary. This is the chart that tells you the rate of the tax based on salary range.
I tried this code,
Dim federaltaxrate As Integer
Dim federaltax = (salary.Text * federaltaxrate)
If salary.Text >= 0 Then
If salary.Text <= 50 Then
federaltaxrate = 0
End If
ElseIf salary.text <= 500 Then
If salary.Text >= 50 Then
federaltaxrate = 0.1
End If
ElseIf salary.text <= 2500 Then
If salary.Text >= 500 Then
federaltaxrate = 45 + 0.15 * salary.Text - 500
End If
ElseIf salary.text <= 5000 Then
If salary.Text >= 2500 Then
federaltaxrate = 345 + 0.2 * salary.Text - 2500
End If
ElseIf salary.text >= 5000 Then
federaltaxrate = 845 + 0.25 * salary.Text - 5000
End If
Else
End If
I have a listbox that shows other information as well but this is what I used to show the calculated info in the listbox.
ListBox1.Items.Add("Federal Tax: $" + federaltax.ToString)
When I run this code and input in a random salary, the federal tax shows up as 0.
Do I need to convert the salary into weekly gross pay, if so how would I go on about writing the code that finds the federal tax rate based on the salary and it's range.
You might be having trouble with order of precedence of the arithmetic operations. I think a Select Case is cleaner.
Private Function GetFederalTax(GrossPay As Decimal) As Decimal
Dim FederalTax As Decimal
Select Case GrossPay
Case < 50
FederalTax = 0
Case < 500
FederalTax = CDec((GrossPay - 51) * 0.1)
Case < 2500
FederalTax = CDec(((GrossPay - 500) * 0.15) + 45)
Case < 5000
FederalTax = CDec(((GrossPay - 2500) * 0.2) + 345)
Case Else
FederalTax = CDec(((GrossPay - 5000) * 0.25) + 845)
End Select
Return FederalTax
End Function
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim grossPay As Decimal
If Decimal.TryParse(TextBox1.Text, grossPay) Then
Dim tax = GetFederalTax(grossPay)
Debug.Print($"Gross {grossPay} Tax {tax}")
ListBox1.Items.Add(String.Format("Federal Tax {0}, Gross Pay {1}", tax, grossPay)) '***EDIT***
Else
MessageBox.Show("Please enter a valid number.")
End If
End Sub
The sample test produced the following in the Immediate Window.
Gross 45 Tax 0
Gross 700 Tax 75
Gross 8000 Tax 1595
Gross 2501 Tax 345.2
Gross 2800 Tax 405
Firstly, your Boolean logic is all wrong. If the salary value was 51, you'd satisfy the first outer condition (>= 0) and then fail the first inner condition (<= 50). There would not be any further comparisons performed - which you would know if you'd debugged - so no tax calculation would ever be performed.
Secondly, your calculations are OK but you're misusing the results. Those calculation get the amount of tax to be paid, not the rate. The rates are 10%, 15%, 20% and 25%, which are already contained in your calculations. Get rid of that second variable and just assign the results of appropriate calculations to the one variable.
I would do it like this:
Dim salaryAmount = CDec(salary.Text)
Dim taxAmount As Decimal = Decimal.Zero
If salaryAmount > 5000D Then
taxAmount = 845D + 0.25D * (salaryAmount - 5000D)
ElseIf salaryAmount > 2500D Then
taxAmount = 345D + 0.2D * (salaryAmount - 2500D)
ElseIf salaryAmount > 500D Then
taxAmount = 45D + 0.15D * (salaryAmount - 500D)
ElseIf salaryAmount > 50D Then
taxAmount = 0.1D * (salaryAmount - 50D)
End If
'Use taxAmount here.
This uses appropriate data types throughout, i.e. it does not perform arithmetic on String values and it uses Decimal for currency values. The D suffix on the literals forces them to be type Decimal rather than Integer or Double.
It also works from biggest to smallest to simplify the Boolean expressions.
The Nested If should be combined like below as it is missing few cases
If salary.Text >= 0 And salary.Text <= 50 Then
federaltaxrate = 0
ElseIf salary.text <= 500 And salary.Text >= 50 Then
federaltaxrate = 0.1
ElseIf salary.text <= 2500 AND salary.Text >= 500 Then
federaltaxrate = 45 + 0.15 * salary.Text - 500
End If

How to set items check in checklistbox?

I use SetItemChecked method to automatically check the checklistbox but it does not work. Anyone have a look to my code and please give a solution?
Private Sub Check(value As Double)
If 0 <= value < 20 Then
Me.CheckedListBox1.SetItemChecked(0, True)
ElseIf 20 <= value < 40 Then
Me.CheckedListBox1.SetItemChecked(1, True)
ElseIf 40 <= value < 60 Then
Me.CheckedListBox1.SetItemChecked(2, True)
ElseIf 60 <= value < 80 Then
Me.CheckedListBox1.SetItemChecked(3, True)
Else
Me.CheckedListBox1.SetItemChecked(4, True)
End If
End Sub
Then I call check(60) and it returns the 1st item check. It is wrong?
You need to correct your conditions as shown below also Clear
Private Sub Check(value As Double)
Me.CheckedListBox1.ClearSelected()
If 0 <= value And value < 20 Then
Me.CheckedListBox1.SetItemChecked(0, True)
ElseIf 20 <= value And value < 40 Then
Me.CheckedListBox1.SetItemChecked(1, True)
ElseIf 40 <= value And value < 60 Then
Me.CheckedListBox1.SetItemChecked(2, True)
ElseIf 60 <= value And value< 80 Then
Me.CheckedListBox1.SetItemChecked(3, True)
Else
Me.CheckedListBox1.SetItemChecked(4, True)
End If
End Sub
The first If-statement will always evaluate to True.
Because True is converted to 1 and False is converted to 0.
It's getting clearer if you look at this:
If (0 <= value) < 20 Then
So no matter which number is contained in value, the condition will be either...
True < 20
..or...
False < 20
For more information see here: Convert Boolean to Integer in VB.NET
So you need to change the conditions like following:
If 0 <= value And value < 20 Then ...

System.InvalidCastException Issue

I can't understand how I should fix my code. I keep getting this error.
InvalidCastException was unhandled
An unhandled exception of type 'System.InvalidCastException' occurred
in Microsoft.VisualBasic.dll
Additional information: Conversion from string "" to type 'Double' is
not valid.
I'm confused on how to fix this. I don't understand the error. It starts at the beginning of the If. Here is the code I am using:
Public class Income_Tax
Dim rate as Double
Dim difference as Double
Private Sub textboxqitni_TextChanged(sender As Object, e As EventArgs) Handles textboxqitni.TextChanged
If textboxqitni.Text >= 0 And textboxqitni.Text <= 10000 Then
textboxittd.Text = textboxqitni.Text * 0.05
ElseIf textboxqitni.Text >= 10000 And textboxqitni.Text <= 30000 Then
difference = textboxqitni.Text - 10000
rate = difference * 0.1
textboxittd.Text = rate + 500
ElseIf textboxqitni.Text >= 30000 And textboxqitni.Text <= 70000 Then
difference = textboxqitni.Text - 30000
rate = difference * 0.15
textboxittd.Text = rate + 2500
ElseIf textboxqitni.Text >= 70000 And textboxqitni.Text <= 140000 Then
difference = textboxqitni.Text - 70000
rate = difference * 0.2
textboxittd.Text = rate + 8500
ElseIf textboxqitni.Text >= 140000 And textboxqitni.Text <= 250000 Then
difference = textboxqitni.Text - 140000
rate = difference * 0.25
textboxittd.Text = rate + 22500
ElseIf textboxqitni.Text >= 250000 And textboxqitni.Text <= 500000 Then
difference = textboxqitni.Text - 250000
rate = difference * 0.3
textboxittd.Text = rate + 50000
ElseIf textboxqitni.Text >= 500000 And textboxqitni.Text <= 999999999999999 Then
difference = textboxqitni.Text - 500000
rate = difference * 0.32
textboxittd.Text = rate + 125000
End If
End Sub
The first thing I suggest is to use a decimal datatype for your calculations.
It seems that your mathematical operations involve monetary values and in this case you should always use a decimal datatype to avoid floating point errors well documented.
Next problem is caused by the fact you think that a string containing only digits can be used in mathematical expressions. This is not true and works (sometime) only if you set Option Strict Off in your program options.
This settings was left to Off to facilitate the porting of VB6 programs to VB.NET and you should set it to ON for new code to avoid the subtle bugs introduced by automatic conversion of values.
You should always convert that string to a numeric variable, do the math with the numeric variable and then, if you need to display the result, convert back the number to a string.
Public Class Income_Tax
Dim rate As Decimal
Dim difference As Decimal
Private Sub textboxqitni_TextChanged(sender As Object, e As EventArgs) Handles textboxqitni.TextChanged
' Use a decimal variable to extract the current value typed
Dim value As Decimal
' You don't want to continue if the input is not a valid number
if Not decimal.TryParse(textboxqitni.Text, value) Then
MessageBox.Show("Not a valid number")
return
End If
' Use AndAlso to express logical AND
If value >= 0 AndAlso value <= 10000 Then
value = value * 0.05
' <= 10000 is already takes, the elseif should be for > 10000
ElseIf value > 10000 AndAlso value <= 30000 Then
difference = value - 10000
rate = difference * 0.1
value = rate + 500
ElseIf value > 30000 AndAlso value <= 70000 Then
difference = value - 30000
rate = difference * 0.15
value = rate + 2500
ElseIf value > 70000 AndAlso value <= 140000 Then
difference = value - 70000
rate = difference * 0.2
value = rate + 8500
' ..............................
' Complete with other else if
' ..............................
End If
' Finally set the value back to textbox
textboxittd.Text = value.ToString()
End Sub
Try this
Try
Dim tbval As Integer = Integer.Parse(textboxqitni.Text)
If tbval >= 0 And tbval <= 10000 Then
textboxittd.Text = tbval * 0.05
ElseIf tbval >= 10000 And tbval <= 30000 Then
difference = tbval - 10000
rate = difference * 0.1
textboxittd.Text = rate + 500
ElseIf tbval >= 30000 And tbval <= 70000 Then
difference = tbval - 30000
rate = difference * 0.15
textboxittd.Text = rate + 2500
ElseIf tbval >= 70000 And tbval <= 140000 Then
difference = tbval - 70000
rate = difference * 0.2
textboxittd.Text = rate + 8500
ElseIf tbval >= 140000 And tbval <= 250000 Then
difference = tbval - 140000
rate = difference * 0.25
textboxittd.Text = rate + 22500
ElseIf tbval >= 250000 And tbval <= 500000 Then
difference = tbval - 250000
rate = difference * 0.3
textboxittd.Text = rate + 50000
ElseIf tbval >= 500000 And tbval <= 999999999999999 Then
difference = tbval - 500000
rate = difference * 0.32
textboxittd.Text = rate + 125000
End If
Catch ex As Exception
MsgBox("Error Occured" & vbCrLf & ex.Message)
End Try

Can't understand why my variable doesn't change

I'm building a little time > pay conversion program in VB. I'm really new to VB and don't understand why my variable pay doesn't calculate like it should. I plug in 5 5's as a test and get $0.
Dim total As Double = 0.0
Dim timeCounter As Integer = 0
Dim time As Integer = 0
Dim pay As Double = 0.0
While timeList.Items.Count < 5
time = timeList.Items(timeCounter)
total += time
timeCounter += 1
End While
If total >= 0 And total <= 40 Then
If total >= 0 And total <= 20 Then
pay = total * 10
ElseIf total >= 21 And total <= 30 Then
pay = total * 12
ElseIf total >= 31 And total <= 40 Then
pay = total * 15
Else
PayLabel.Text = "Error"
End If
End If
PayLabel.Text = "$" & pay
Your syntax should be something like this:
For intCount = 0 To timeList.Items.Count
time = timeList.Items(intCount)
total += time
Next intCount
This will avoid an infinite loop.
To fix your 40+ issue:
If total >= 0 And total <= 40 Then
If total >= 0 And total <= 20 Then
pay = total * 10
ElseIf total >= 21 And total <= 30 Then
pay = total * 12
ElseIf total >= 31 And total <= 40 Then
pay = total * 15
End If
Else
PayLabel.Text = "Error"
End If
this would be my fix into a console apps
for process will return $0, second $100
Module Module1
Sub Main()
Dim timeList As New List(Of Integer)
timeList.AddRange(New Integer() {1, 2, 3, 4, 5, 6})
process(timeList)
timeList.Clear()
timeList.AddRange(New Integer() {1, 2, 3, 4})
process(timeList)
Console.Read()
End Sub
Private Sub process(timeList As List(Of Integer))
Dim total As Double = 0.0
Dim timeCounter As Integer = 0
Dim time As Integer = 0
Dim pay As Double = 0.0
While timeList.Count < 5 AndAlso timeCounter < timeList.Count
time = timeList(timeCounter)
total += time
timeCounter += 1
End While
If total >= 0 And total <= 40 Then
If total >= 0 And total <= 20 Then
pay = total * 10
ElseIf total >= 21 And total <= 30 Then
pay = total * 12
ElseIf total >= 31 And total <= 40 Then
pay = total * 15
Else
Console.WriteLine("error")
End If
End If
Console.WriteLine("$" & pay)
End Sub
End Module
This could be better solved with a functional approach. To get the sum of the list of integers do the following:
Dim totalTime = timeList.Sum()
Then you can follow the logic you laid out. I would highly recommend learning to use Linq Set Functions to make your code your readable and easier to understand. Good Luck.

VB.net loop through if-then statements?

I have written a private sub which gets the current time and works out which time bracket (from a timespan array) the current time falls into. Given that there are ten time brackets I'm testing for, the code is repetitive and only the integer index of the array and the result integer change between each if statement.
If DateTime.Now.TimeOfDay >= tmeToday(0) AndAlso DateTime.Now.TimeOfDay <= tmeToday(1) Then
intPeriodFrid = 0 'ext morning; 8am - 9am
intNextBell = 1
ElseIf DateTime.Now.TimeOfDay >= tmeToday(1) AndAlso DateTime.Now.TimeOfDay <= tmeToday(2) Then
intPeriodFrid = 1 'morning break; 9am - 9:05am
intNextBell = 2
... ridiculous amounts of repetition later
ElseIf DateTime.Now.TimeOfDay >= tmeToday(10) AndAlso DateTime.Now.TimeOfDay <= tmeToday(11) Then
intPeriodFrid = 10 'ext afternoon; 3:10pm - 4:10pm
intNextBell = 11
End If
Then it hit me I could probably do it like this:
For value As Integer = 0 To 10
If DateTime.Now.TimeOfDay >= tmeToday(value) AndAlso DateTime.Now.TimeOfDay <= tmeToday(value + 1) Then
intPeriodFrid = value
intNextBell = (value + 1)
Exit For
End If
Next
This would/will be my first ever use of a loop (I'm ten weeks into a VB.NET based course), so I lack confidence in this as a solution, will it work? Any weaknesses/problems I need to look out for if I implement this?