dantab22
dantab22

Reputation: 31

Banker Rounding in VBA?

I am trying to build a Mortgage Amortization calculator using VBA. When I type the formulas in the worksheet and reference each cell to the formula then my calculator works fine. It requires me to drag all my formulas down to duration of the loan. For example, if loan duration is 300 months, I can just drag the formulas to say cell number 300 and it will work fine.

PROBLEM: When I use VBA code to do the same I get essentially a rounding problem where after the end of the term, I don't get a balance of 0.00. I have tried both normal round function and Application.WorksheetFunction.Round and it still yields the same result. Why do my calculations work on the worksheet but when translated into VBA code I get different results? Link to screenshot of my spreadsheet which corresponds to the code: enter image description here

Option Explicit

Sub Loan2()

Dim i As Integer, LD As Integer
LD = Range("C5").Value
Range("B11", "G1000").ClearContents
Range("B11", "G1000").Interior.ColorIndex = xlNone
For i = 1 To LD
    Cells(10 + i, 2).Value = i 'Payment Period
    Cells(10 + i, 3) = Application.WorksheetFunction.Round(Range("C7").Value, 2) 'Monthly Payment
    Cells(10 + i, 5) = Application.WorksheetFunction.Round(Cells(10 + i - 1, 6) * (Range("C4").Value / 12), 2) 'Interest payment
    Cells(10 + i, 4) = Application.WorksheetFunction.Round(Cells(10 + i, 3).Value - Cells(10 + i, 5).Value, 2) 'Principle payment
    Cells(10 + i, 6).Value = Cells(10 + i - 1, 6).Value - Cells(10 + i, 4).Value 'Balance
    Cells(10 + i, 7) = Cells(10 + i, 4).Value + Cells(10 + i, 5).Value 'Sum of principle and interest.
Next i

End Sub

Upvotes: 2

Views: 1205

Answers (1)

T.M.
T.M.

Reputation: 9948

An alternative to the worksheet function (avoiding bankers' rounding):

Function roundIt(ByVal d As Double, ByVal nDigits As Integer) As Double
' Purpose: avoid so called bankers' rounding in VBA (5 always rounds even)
If nDigits > 0 Then
   ' if european colon instead of point separartor
   ' roundIt= val(Replace(Format(d, "0." & String(nDigits, "0")), ",", "."))
     roundIt= val(Format(d, "0." & String(nDigits, "0")))
Else
   ' if european colon instead of point separartor
   ' roundIt =  val(Replace(Format(d / (10 ^ nDigits), "0."), ",", "."))
   roundIt = val(Format(d / (10 ^ nDigits), "0."))
End If
End Function

Always use "Option explicit" to check your declarations. Code gets more readable if you use a Type structure. Write this in the declaration head of your module.

Option Explicit

Type TLoan
   Interest       As Double
   LD             As Integer
   Principal      As Double
   Annuity        As Double
End Type

Here is your code with some additions

Sub Loan2()
Dim loan As TLoan                                   ' declare loan as of type TLoan
Dim i As Integer                                    ' no more use for LD ", LD As Integer"
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("MySheetName")     ' fully qualified range

With loan
  .Interest = ws.Range("C4").Value
  .LD = ws.Range("C5").Value
  .Principal = ws.Range("C6").Value
  .Annuity = ws.Range("C7").Value
End With

With ws
  .Range("B10").Value = 0
  .Range("F10").Value = loan.Principal              ' principal
  .Range("B11", "G1000").ClearContents
  .Range("B11", "G1000").Interior.ColorIndex = xlNone

  For i = 1 To loan.LD
    .Cells(10 + i, 2).Value = i                     'Payment Period
    .Cells(10 + i, 3) = roundIt(loan.Annuity, 2)   'Monthly Payment
    .Cells(10 + i, 5) = roundIt(.Cells(10 + i - 1, 6) * (loan.Interest / 12), 2) 'Interest payment
    .Cells(10 + i, 4) = roundIt(.Cells(10 + i, 3).Value - .Cells(10 + i, 5).Value, 2) 'Principle payment
    .Cells(10 + i, 6).Value = Cells(10 + i - 1, 6).Value - .Cells(10 + i, 4).Value    'Balance
    .Cells(10 + i, 7) = .Cells(10 + i, 4).Value + .Cells(10 + i, 5).Value             'Sum of principle and interest.
  Next i
End With
End Sub

Additional tip (autofill Routine)

Try to use an autofill routine as shown in "Excel-VBA-autofill multiple cells with formula Excel VBA: AutoFill Multiple Cells with Formulas, if you want to include formulas instead of pure values.

Attention: This code refers to another problem with different ranges! Try and play around.

Sub FillDown()

Dim strFormulas(1 To 3) As Variant

With ThisWorkbook.Sheets("Formeln")
    strFormulas(1) = "=SUM(A2:B2)"
    strFormulas(2) = "=PRODUCT(A2:B2)"
    strFormulas(3) = "=A2/B2"
'    Pattern Formulas
    .Range("C2:E2").Formula = strFormulas
'    AutoFill Target
    .Range("C2:E11").FillDown
End With

End Sub

Upvotes: 0

Related Questions