I want to create a function which give me what contribution an employee has to make to a pension plan in function of its salary (with given down and upper limit) and in function of its age (doesn't contribute before 25 and after 64).
With the following code, I try to achieve that. I may have spend too much time on front of my screen but i don't see the problem. The debugger runs fine but I keep getting a "#Value!" alert. It may be the If-statment within another If. If someone may see where the problem could be, it would be very helpful
Option Explicit
Constant M = 1175
Function coti_min_LPP(x As Integer, salaire_AVS As Double)
Dim salaire_coord As Double
'The basis for the calculation uses the salary in different layers
If salaire_AVS < 18 * M Then
salaire_coord = 0
ElseIf salaire_AVS > 18 * M And salaire_AVS < 24 * M Then
salaire_coord = 3 * M
ElseIf salaire_AVS > 24 * M Then
salaire_coord = salaire_AVS - 21 * M
End If
'Under a certain limit, the contribution is a percentage of the basis
'according to the age
If salaire_AVS < 72 * M Then
If x < 25 Then
coti_min_LPP = 0
ElseIf x > 24 And x < 35 Then
coti_min_LPP = salaire_coord * 0.07
ElseIf x > 34 And x < 45 Then
coti_min_LPP = salaire_coord * 0.1
ElseIf x > 44 And x < 55 Then
coti_min_LPP = salaire_coord * 0.15
ElseIf x > 54 And x < 65 Then
coti_min_LPP = salaire_coord * 0.18
ElseIf x > 64 Then
coti_min_LPP = 0
End If
Else
'Above the limit, it is the percentage of a fixed amount
If x < 25 Then
coti_min_LPP = 0
ElseIf x > 24 And x < 35 Then
coti_min_LPP = 51 * M * 0.07
ElseIf x > 34 And x < 45 Then
coti_min_LPP = 51 * M * 0.1
ElseIf x > 44 And x < 55 Then
coti_min_LPP = 51 * M * 0.15
ElseIf x > 54 And x < 65 Then
coti_min_LPP = 51 * M * 0.19
ElseIf x > 64 Then
coti_min_LPP = 0
End If
End If
End Function
There are two immediate things that result in an issue:
Instead of Constant M = 1175 you should use Private Const M As Long = 1175. Why Long? Please look at the line If salaire_AVS < 72 * M Then if you add watch and go through your code in the debbuger you will find out that, if M is declared as an integer, after this line (according to watch window) M has value "out of context". This is basically due to the fact that you have achieved integer overflow. Please consider following code:
Example 1:
Sub test2()
Dim a As Integer
Dim b As Double
a = 1175
b = 15
Debug.Print b < 72 * a
End Sub
Option Explicit is a good practice, however requires you to declare all of the variables in your code. Declare them. You may remove Option Explicit for testing purposes. Some lecture on variable declaration: http://www.excelfunctions.net/VBA-Variables-And-Constants.html
After above changes your function works for me (tested =coti_min_LPP(27,19*1175))
Hope that helps. Btw. Please notice that having so many nested ifs with hardcoded values is troublesome to maintain, control and usually is not considered as good coding practice.
Related
So I was just wondering how to calculate an average in visual basic code?
I currently have a form created and the user is to enter 6 numbered for 6 courses and they must be in textboxes. I know that average is the 6 numbers added together divided by the count but I don't know how to grab the numbers from the textbox to calculate the average.
I've searched online for the answer to this but nothing pertains to this exact problem. My textbook is also of no help.
Any help would be greatly appreciated.
Dim input As Integer
If Integer.TryParse(InputTextbox1.Text, input) Then
If input >= 92 And input <= 100 Then
OutputTextbox1.Text = "A+"
ElseIf input >= 88 And input <= 91 Then
OutputTextbox1.Text = "A"
ElseIf input >= 85 And input <= 87 Then
OutputTextbox1.Text = "A-"
ElseIf input >= 82 And input <= 84 Then
OutputTextbox1.Text = "B+"
ElseIf input >= 78 And input <= 81 Then
OutputTextbox1.Text = "B"
ElseIf input >= 75 And input <= 77 Then
OutputTextbox1.Text = "B-"
ElseIf input >= 72 And input <= 74 Then
OutputTextbox1.Text = "C+"
ElseIf input >= 68 And input <= 71 Then
OutputTextbox1.Text = "C"
ElseIf input >= 65 And input <= 67 Then
OutputTextbox1.Text = "C-"
ElseIf input >= 55 And input <= 64 Then
OutputTextbox1.Text = "D"
ElseIf input <= 54 Then
OutputTextbox1.Text = "F"
End If
Else
ErrorTextbox.Text = "Please ensure that what you input is a number between 0 and 100"
End If
This is the code I have currently there is 6 textboxes using the above code to transfer numbers to letters. The numbers that the user enters is what i need to calculate into the average.
Thanks
Try this:
first thing i did is that i total all textbox numbers and then divide to total number so that i can get the average
Note: dont allow textbox to input a letters because it will error
i converted the textbox text to double so that it will consider as number and not letters.
Public Class Form4
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim average As Double = 0.0
Dim total As Double = 0.0
total = CDbl(TextBox1.Text) + CDbl(TextBox2.Text) + CDbl(TextBox3.Text) + CDbl(TextBox4.Text) + CDbl(TextBox5.Text) + CDbl(TextBox6.Text)
average = total / 6
TextBox7.Text = average.ToString()
End Sub
End Class
Modified: The label_grade is the letter of the grade
Public Class Form4
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim average As Double = 0.0
Dim total As Double = 0.0
total = CDbl(TextBox1.Text) + CDbl(TextBox2.Text) + CDbl(TextBox3.Text) + CDbl(TextBox4.Text) + CDbl(TextBox5.Text) + CDbl(TextBox6.Text)
average = total / 6
TextBox7.Text = average.ToString()
If average >= 92 And average <= 100 Then
label_Grade.Text = "A+"
ElseIf average >= 88 And average <= 91 Then
label_Grade.Text = "A"
ElseIf average >= 85 And average <= 87 Then
label_Grade.Text = "A-"
ElseIf average >= 82 And average <= 84 Then
label_Grade.Text = "B+"
ElseIf average >= 78 And average <= 81 Then
label_Grade.Text = "B"
ElseIf average >= 75 And average <= 77 Then
label_Grade.Text = "B-"
ElseIf average >= 72 And average <= 74 Then
label_Grade.Text = "C+"
ElseIf average >= 68 And average <= 71 Then
label_Grade.Text = "C"
ElseIf average >= 65 And average <= 67 Then
label_Grade.Text = "C-"
ElseIf average >= 55 And average <= 64 Then
label_Grade.Text = "D"
ElseIf average <= 54 Then
label_Grade.Text = "F"
End If
End Sub
I am trying to find the x intercept of a 4th degree function by incrementing the x value. I feel like this way doesnt work always and isnt the most efficient way to do this, is there another way I am missing?
My code is:
Sub Findintercept()
Dim equation As Double, x As Double, A As Double, B As Double, C As Double, D As Double, E As Double
A = 0.000200878
B = -0.002203704
C = 0.0086
D = -0.02333
E = 0.02033
x = 0
equation = A * x ^ 4 + B * x ^ 3 + C * x ^ 2 + D * x + E
While (equation > 0.00001 Or equation < -0.00001)
If (x > 5) Then
MsgBox "Could not find intercept"
equation = 0
Else
x = x + 0.0001
equation = A * x ^ 4 + B * x ^ 3 + C * x ^ 2 + D * x + E
End If
Wend
MsgBox x
End Sub
Sometimes it fails to find the intercept hence the IF condition in the while loop. (Im always expecting the intercept to be less than 5!
Your method suffers from two problems:
You assume a step size to change x. The step could be too large, causing you to "walk past" the value your are looking for. To deal with this, you make a small step size, which can mean an excessively large number of iterations are needed to find the solution.
You always assume the same direction to change x. Even with seemingly small values for your step size, you could "walk past" the solution, and have no means to change direction. Or, your initial guess may be on the wrong side of the solution, and you never find an answer.
The Newton-Raphson method handles both of these issues neatly. You do still need to choose your initial guess somewhat close to the root you are looking for.
This method does have potential problems, but for polynomials such as the one you are dealing with, it is quite good.
Below is a simple VBA sub that implements this method. It solves your problem in 4 iterations. I recommend adjusting the initial guess (xii) a lot to see how it impacts the solution you get.
Sub SimpleNewtonRaphson()
Const Tol As Double = 1E-06
Const MaxIter As Long = 50
Dim xi As Double, xii As Double, deriv As Double
Dim IterCount As Long
' Initialize
xi = 0#
xii = 1#
IterCount = 0
' Method
Do While IterCount < MaxIter And Abs(xii - xi) > Tol
xi = xii
deriv = myDeriv(xi)
If deriv = 0# Then Exit Do
xii = xi - myFunc(xi) / deriv
IterCount = IterCount + 1
Loop
' Results
If deriv = 0 Then MsgBox "Ran into a 0 derivative, modify initial guess"
If IterCount >= MaxIter Then MsgBox "MaxIterations reached"
If Abs(xii - xi) <= Tol Then MsgBox "Solution found #" & vbCrLf & "F(" & xii & ") = " & myFunc(xii)
End Sub
... and two VBA functions for your equation and it's derivative ...
Function myFunc(x As Double) As Double
Const A As Double = 0.000200878
Const B As Double = -0.002203704
Const C As Double = 0.0086
Const D As Double = -0.02333
Const E = 0.02033
myFunc = A * x ^ 4 + B * x ^ 3 + C * x ^ 2 + D * x + E
End Function
Function myDeriv(x As Double) As Double
Const A As Double = 0.000200878
Const B As Double = -0.002203704
Const C As Double = 0.0086
Const D As Double = -0.02333
myDeriv = 4 * A * x ^ 3 + 3 * B * x ^ 2 + 2 * C * x + D
End Function
I Need a help in Excel VBA. I want to develop a function that will automatically apply the function to selected range of Cells. My Sample Code is Here it work Independently for a single row I want to apply it for minimum 500 rows.
Sub Value() ' ' Value For the Insurance Rate
Dim percentage As Double
Dim year As Double
percentage = Sheet5.Range("R2").Value
year = Sheet5.Range("Q2").Value
If percentage <= 85 And year <= 25 Then
Sheet5.Range("S2").Value = Sheet4.Range("D13").Value
ElseIf percentage <= 85 And year > 25 Then
Sheet5.Range("S2").Value = Sheet4.Range("C13").Value
ElseIf percentage > 85 And percentage <= 90 And year <= 25 Then
Sheet5.Range("S2").Value = Sheet4.Range("D8").Value
ElseIf percentage > 85 And percentage <= 90 And year > 25 Then
Sheet5.Range("S2").Value = Sheet4.Range("C8").Value
ElseIf percentage > 90 And percentage <= 95 And year <= 25 Then
Sheet5.Range("S2").Value = Sheet4.Range("D5").Value
ElseIf percentage > 90 And percentage <= 95 And year > 25 Then
Sheet5.Range("S2").Value = Sheet4.Range("C5").Value
ElseIf percentage > 95 And year <= 25 Then
Sheet5.Range("S2").Value = Sheet4.Range("D3").Value
ElseIf percentage > 95 And year > 25 Then
Sheet5.Range("S2").Value = Sheet4.Range("C3").Value
End If
End Sub
You're pretty close. I just converted your procedure into a User Defined Function, which can then be used like built-in Excel functions in the Excel Window.
Here's the code:
Function myValue(percentage As Double, year As Double) ''Value For the Insurance Rate
If percentage <= 85 And year <= 25 Then
myValue = Sheet4.Range("D13").Value
ElseIf percentage <= 85 And year > 25 Then
myValue = Sheet4.Range("C13").Value
ElseIf percentage > 85 And percentage <= 90 And year <= 25 Then
myValue = Sheet4.Range("D8").Value
ElseIf percentage > 85 And percentage <= 90 And year > 25 Then
myValue = Sheet4.Range("C8").Value
ElseIf percentage > 90 And percentage <= 95 And year <= 25 Then
myValue = Sheet4.Range("D5").Value
ElseIf percentage > 90 And percentage <= 95 And year > 25 Then
myValue = Sheet4.Range("C5").Value
ElseIf percentage > 95 And year <= 25 Then
myValue = Sheet4.Range("D3").Value
ElseIf percentage > 95 And year > 25 Then
myValue = Sheet4.Range("C3").Value
End If
End Function
Then in cell S2 (or any other cell you want to use the function) you would enter
=myValue(R2,Q2)
Also note, that I change the name of the function to myValue to not run into issues with the built in Value members in VBA.
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.
I have the following code:
Sub Main()
Dim a As Integer = 8 * 60
Dim b As Integer
Dim c As Integer
If a < (6 * 60) Then
b = 0 And c = 0
ElseIf a >= 6 * 60 And a < 9 * 60 Then
b = 30 And c = 1
Else
b = 45 And
c = 1
End If
MsgBox(b)
End Sub
Thinks i dont understand and where i need someones help:
"c=0" and "c=1" are underlined with the error: Strict on doesnt allow implicit convertation from boolean to integer. WHY? I declared c as integer!
Variable "b" and "c" are always "0" even though in the case above they should be b=30 and c = 1.
can anyone please explain me this behaviour.
You are using the And keyword where it is not allowed. And is a logical operator (along with Or, AndAlso, OrElse.)
The following should work.
Sub Main()
Dim a As Integer = 8 * 60
Dim b As Integer
Dim c As Integer
If a < (6 * 60) Then
b = 0
c = 0
ElseIf a >= 6 * 60 And a < 9 * 60 Then
b = 30
c = 1
Else
b = 45
c = 1
End If
MsgBox(b)
End Sub