How to Round in VBA - vba

I'm using worksheetFunction.pmt and need the output in the msgbox to be rounded to 2 decimal places or to display just the whole number.
I have declared the variables as Double and tried to add Round into the msgbox output but get a runtime error 13. I can't figure out where to put the Round function
Sub pmt()
Dim Sum, Rate, Period As Double
Sum = InputBox("Enter the sum of the loan")
Rate = InputBox("Enter the interest rate")
Period = InputBox("Enter the number of payments")
MsgBox "Your PMT is: $ " & WorksheetFunction.pmt(Rate, Period, -Sum) & ""
End Sub
I expect the result to return only 2 decimal places. Is it possible to round the worksheetFunction.pmt

Just use the VBA Round function:
Sub pmt()
'Take care when naming your variables
'Dim dlbSum as Double, dblRate as Double, dblPeriod as Double
'Defining Period as Dboule doesn't make sense anyway
Dim Sum, Rate, Period As Double
Sum = InputBox("Enter the sum of the loan")
'You should consider error checking, entering the percentage symbol will create an error in the calculations
Rate = InputBox("Enter the interest rate")
Period = InputBox("Enter the number of payments")
MsgBox "Your PMT is: $ " & Round(WorksheetFunction.pmt(Rate, Period, -Sum), 2) & ""
End Sub

Related

Convert range to integer

In the following code, CalendarMonths is a range containing month names. endDate is also a range.
I need to translate those names into month numbers, however the following method using Month function returns "type mismatch" error (even if I skip CInt):
For Each CalendarMonth In CalendarMonths
If CInt(Month(CalendarMonth)) = CInt(Month(endDate)) Then
If you have a month as String and want to convert to Long:
Sub skjdffhs()
Dim s As String, n As Long
s = "January"
n = Month(CDate("1 " & s & " 2000"))
MsgBox n
End Sub
(this is for the US locale)

checking data type in VBA

I have a program in VBA in which I'd like the user to only enter a number. I want to be able to catch when they they enter a string and have them try again. This is what I've tried:
Sub getInterest()
annualInterest = InputBox("Please enter your annual interest rate as a decimal. ")
If TypeOf annualInterest Is Double Then
'Continue with program
Else
Call getInterest()
End If
End Sub
But this doesn't work.
IsNumeric returns a boolean & doesn't tell you what the type of data user entered, only if it passed or failed numeric check. And while it may work in your case another option is VarType function.
VarType function returns an Integer indicating the subtype of a variable
Sub getInterest()
annualinterest = InputBox("Please enter your annual interest rate as a decimal. ")
If VarType(annualinterest) = vbDouble OR VarType(annualinterest)=vbSingle Then
'crunch interest
Else
getInterest
End If
End Sub
Try something like this...
Sub getInterest()
Dim annualInterest As Double
Do While annualInterest = 0
annualInterest = Application.InputBox("Please enter your annual interest rate as a decimal.", "Annual Interest Rate!", Type:=1)
Loop
MsgBox annualInterest
End Sub
Your syntax in second row is wrong. please try below code. Code will proceed only if user input is a valid number.
Sub getInterest()
annualinterest = InputBox("Please enter your annual interest rate as a decimal. ")
If IsNumeric(annualinterest) Then
'Continue with program
Else
Call getInterest
End If
End Sub
I think you can simply force a numeric entry in Excel VBA by using the existing parameters.
annualInterest = Application.InputBox("Please enter your annual interest rate as a decimal. ", , , , , , , 1)
It will ensure a valid numeric entry and can save the call.

vba average calculator userform

Hey im trying to write a small VBA program that calculates the average quiz score the problem is when i enter in the third number it comes back incorrect after doing the first two right.What am i missing?
This is the design view
Option Explicit
Dim total As Double
Dim number As Double
Dim average As Double
Private Sub CommandButton1_Click()
If IsNumeric(TextBox1.Value) = True Then
total = CDbl(average + TextBox1.Value)
number = CDbl(number + 1)
average = CDbl(total / number)
TextBox2.Value = number
TextBox3.Value = average
TextBox1.Value = ""
Else
MsgBox ("please enter a number")
TextBox1.Value = ""
End If
End Sub
Your math is off. If you want to do it, using the previous average, and the new value, then the formula you should use is this:
( [old average] + ( [new value] / [count - 1] ) ) / ( [count] / [count - 1] )
However, as you might see, this is not a very easy-to-read design. I would go for a design, using an array. That way you can keep the math a lot more intuitive, plus you can look back at old score, if you want. The easiest design is probably to keep the array the size of your score count. This requires redim() each time you add a new score. From a performance point-of-view, this is quite bad practice. But in your tiny calculator, thats hardly going to be a problem.
I think you should get number, average, and total value before you do the calculations:
Option Explicit
Dim total As Double
Dim number As Double
Dim average As Double
Private Sub CommandButton1_Click()
number = 0
average = 0
total = 0
If IsNumeric(TextBox1.Value) = True Then
total = CDbl(average + TextBox1.Value)
number = CDbl(number + 1)
'prevent error
If number > 0 then
average = CDbl(total / number)
Else
average = 0
End If
TextBox2.Value = number
TextBox3.Value = average
TextBox1.Value = ""
Else
MsgBox ("please enter a number")
TextBox1.Value = ""
End If
End Sub
Hope this help.

Conversion from string "" to type 'Double' is not valid In .NET Fiddle's VB

I am writing a project in school (on .NET Fiddle's VB Console) and am encountering an error.
In this task, we have to:
Enter 10 test results with the name of the student.
Validate all data as it is entered and refuse poor data
We need to print out the Mean (arithmetic average), Highest Mark and who got it (assume 1 max per test), Lowest Mark and who got it (assume 1 min per test)
My Personal Code Follows:
Imports System
Public Module Module1
Public Sub Main()
Dim sStudentName As String
Dim iStudentMark As Double
Dim iHighMark As Integer
Dim iLowMark As Integer
Dim iAve As Integer
For List = 1 to 10
Console.WriteLine("Input A Students Name")
sStudentName = Console.ReadLine()
Console.WriteLine("This student's Mark is")
iStudentMark = Console.ReadLine()
Do Until 25<= iStudent Or iStudentMark <= 100
Console.WriteLine("Error. Invalid Percentage. Re-input.")
iStudentMark = Console.ReadLine()
Loop
iAve = iAve + iStudentMark
If iStudentMark > iHighMark Then
iHighMark = iStudentMark
Console.Write("The Highest Percentage has changed. The top score is now " + iStudentMark + " Percent from " + sStudentName)
End If
If iStudentMark < iLowMark Then
iHighMark = iStudentMark
Console.Write("The Highest Percentage has changed. The top score is now " + iStudentMark + " Percent from " + sStudentName)
End If
Next
iAve = iAve/10
Console.WriteLine(iAve)
End Sub
End Module
The Error Message(s) I get is/are:
Run-time exception (line -1): Conversion from string "The Highest
Percentage has chang" to type 'Double' is not valid.
Stack Trace:
[System.FormatException: Input string was not in a correct format.]
[System.InvalidCastException: Conversion from string "The Highest
Percentage has chang" to type 'Double' is not valid.]
I have never been the best at coding, so many thanks to those who try and solve it.
Console.ReadLine() method will return a string you cannot assign it directly to double. you need to cast them as double.
Console.WriteLine("This student's Mark is")
If Not Integer.TryParse(Console.ReadLine(), iStudentMark) Then
Console.WriteLine("Invalid input..! failed to convert")
End If
'you can proceed with iStudentMark

Unexpected String Results

I have the following code to check values entered into two input boxes, if both values are zero then the MsgBox should display "Stop!" (I will change this later to exiting the sub but I am using a MsgBox for testing)
From testing I've seen these results:
A zero in both strings produces the expected message box.
A non zero in the first string followed by any non zero value in the second string does nothing (as expected).
A zero in the first string followed by a second string value equal to or greater than 10 produces the message box (unexpected).
I've also noticed that if the second string is 6-9 it is displayed as x.00000000000001%. I think this is a floating point issue and could be related? This behaviour occurs without the IF... InStr function too.
Option Explicit
Sub Models()
Dim MinPer As String, MaxPer As String, Frmula As String
Dim Data As Worksheet, Results As Worksheet
Set Data = Sheets("Data")
Set Results = Sheets("Results")
Application.ScreenUpdating = False
MinPer = 1 - InputBox("Enter Minimum Threshold Percentage, do not include the % symbol", _
"Minimum?") / 100
MaxPer = 1 + InputBox("Enter Maximum Threshold Percentage, do not include the % symbol", _
"Maximum?") / 100
If (InStr(MinPer, "0") = 0) And (InStr(MaxPer, "0") = 0) Then
MsgBox "STOP!"
End If
' Remainder of code...
This is the most interesting problem I've come across so far in VBA and welcome any discussion about it.
Edit: I use this code to display on screen the paramaters for the end-user to see. Hence how I noticed the .00000000001% issue:
.Range("D2").Value = "Min is " & 100 - MinPer * 100 & "%"
.Range("D3").Value = "Max is " & MaxPer * 100 - 100 & "%"
Two things
1) Declare MinPer, MaxPer as Long or a Double and not a String as you are storing outputs from a calculation
2) Don't directly use the InputBox in the calculations. Store them in a variable and then if the input is valid then use them in the calculation
Dim MinPer As Double, MaxPer As Double, Frmula As String
Dim Data As Worksheet, Results As Worksheet
Dim n1 As Long, n2 As Long
Set Data = Sheets("Data")
Set Results = Sheets("Results")
Application.ScreenUpdating = False
On Error Resume Next
n1 = Application.InputBox(Prompt:="Enter Minimum Threshold Percentage, do not include the % symbol", _
Title:="Minimum?", Type:=1)
On Error GoTo 0
If n1 = False Then
MsgBox "User cancelled"
Exit Sub
End If
On Error Resume Next
n2 = Application.InputBox(Prompt:="Enter Maximum Threshold Percentage, do not include the % symbol", _
Title:="Maximum?", Type:=1)
On Error GoTo 0
If n2 = False Then
MsgBox "User cancelled"
Exit Sub
End If
If n1 = 0 And n2 = 0 Then
MsgBox "STOP!"
End If
MinPer = 1 - (Val(n1) / 100)
MaxPer = 1 + (Val(n2) / 100)
This is because the number "10" has a "0" in the string (second character) so both evaluate to true.
Try this instead:
If (MinPer = "0") And (MaxPer = "0") Then
MsgBox "STOP!"
End If
For additional control save the user input (MinPer , MaxPer) and THEN text them for validity before performing nay mathematical operations on them.
InStr(MinPer, "0") is just checking to see whether the string contains a zero
character.
You need to convert the string value to an integer. Use the IsNumeric and CInt functions
to do that. See this URL:
vba convert string to int if string is a number
Dim minPerINT as Integer
Dim maxPerINT as Integer
If IsNumeric(minPer) Then
minPerINT = CInt(minPer)
Else
minPerINT = 0
End If
If IsNumeric(maxPer) Then
maxPerINT = CInt(maxPer)
Else
maxPerINT = 0
End If
If minPerINT = 0 and maxPerINT=0 Then
MsgBox "STOP!"
End If
Depending on what data can be entered It may also be a good idea to check if the length
of the data is zero using the len() function.