Consulting

Results 1 to 4 of 4

Thread: Solved: Need to sum column totals for month. - My Code seems to be rounding cell values.

  1. #1
    VBAX Expert
    Joined
    Sep 2010
    Posts
    604
    Location

    Solved: Need to sum column totals for month. - My Code seems to be rounding cell values.

    The Function Sum_Visible_Cells seems to be rounding the cell values before giving me a sum total in a msgbox

    See attached workbook where the Actual sum of all the totals for December is: 303,284.39

    but the Sum totaled using code is: 303,281.00

    Would someone be so kind as to point out why that is happening?

    Thanks
    [vba]
    Private Sub CommandButton1_Click()
    'modified slightly Code found at this link
    'http://www.dailydoseofexcel.com/archives/2008/11/26/autofiltering-on-months/
    Dim lMonth As Long, lYear As Long, rngCell As Range, rngCol As Range
    Dim LastRow As Long, wks As Worksheet
    Dim DateCell As Range, rng As Range, x As Long, LValue As String

    Set wks = ActiveSheet
    With wks
    LastRow = ActiveSheet.Range("D" & Rows.Count).End(xlUp).Row

    If ActiveCell.Row = 1 Or ActiveCell.Row > LastRow Then
    MsgBox "Please select a row that has data"
    Exit Sub
    End If

    Set rngCol = ActiveSheet.Range("D2" & LastRow) ' Cost Total Column
    Set rngCell = Range("A2:A" & LastRow) ' Date Column

    Set DateCell = ActiveCell.EntireRow.Cells(1)

    DateCell.Select

    If Not rngCell Is Nothing Then

    If IsDate(DateCell.Value) Then
    lMonth = Month(DateCell.Value)
    lYear = Year(DateCell.Value)

    'Check if there is an autofilter
    If rngCell.Parent.AutoFilterMode Then

    'Make sure DateCell is within autofilter range
    If Not Intersect(DateCell, _
    rngCell.Parent.AutoFilter.Range) Is Nothing Then

    'Create filter
    With rngCell.Parent.AutoFilter
    .Range.AutoFilter DateCell.Column - .Range(1).Column + 1, _
    ">=" & DateSerial(lYear, lMonth, 1), _
    xlAnd, _
    "<=" & DateSerial(lYear, lMonth + 1, 0)
    End With
    End If
    End If
    End If
    End If

    x = Sum_Visible_Cells(rngCol)

    LValue = Format(x, "Currency")

    MsgBox LValue

    Set rng = .Range(.Cells(1, 1), .Cells(LastRow, 4))

    If Not rng Is Nothing Then
    'turn filter off
    .AutoFilterMode = False
    'reset filter
    rng.AutoFilter
    .EnableAutoFilter = True
    End If
    End With

    End Sub

    Function Sum_Visible_Cells(Cells_To_Sum As Object)
    Dim aCell As Range
    Dim total As Long
    Application.Volatile
    For Each aCell In Cells_To_Sum
    If aCell.Rows.Hidden = False Then
    If aCell.Columns.Hidden = False Then
    total = total + aCell.Value
    End If
    End If
    Next
    Sum_Visible_Cells = total
    End Function[/vba]
    Attached Files Attached Files

  2. #2
    Distinguished Lord of VBAX VBAX Grand Master Bob Phillips's Avatar
    Joined
    Apr 2005
    Posts
    25,453
    Location
    Firstly, I had to change the autofilter to work here in the UK. AUtofilter with dates is very flaky, and you have to take care.

    Your problem was that the total variable was a long, so each time you accumulated into there, the pennies were lost.

    [vba]
    Private Sub CommandButton1_Click()
    'modified slightly Code found at this link
    'http://www.dailydoseofexcel.com/archives/2008/11/26/autofiltering-on-months/
    Dim lMonth As Long, lYear As Long, rngCell As Range, rngCol As Range
    Dim LastRow As Long, wks As Worksheet
    Dim DateCell As Range, rng As Range, x As Double, LValue As String

    Set wks = ActiveSheet
    With wks
    LastRow = ActiveSheet.Range("D" & Rows.Count).End(xlUp).Row

    If ActiveCell.Row = 1 Or ActiveCell.Row > LastRow Then
    MsgBox "Please select a row that has data"
    Exit Sub
    End If

    Set rngCol = ActiveSheet.Range("D2" & LastRow) ' Cost Total Column
    Set rngCell = Range("A2:A" & LastRow) ' Date Column

    Set DateCell = ActiveCell.EntireRow.Cells(1)

    DateCell.Select

    If Not rngCell Is Nothing Then

    If IsDate(DateCell.Value) Then

    lMonth = Month(DateCell.Value)
    lYear = Year(DateCell.Value)

    'Check if there is an autofilter
    If rngCell.Parent.AutoFilterMode Then

    'Make sure DateCell is within autofilter range
    If Not Intersect(DateCell, _
    rngCell.Parent.AutoFilter.Range) Is Nothing Then

    'Create filter
    With rngCell.Parent.AutoFilter

    .Range.AutoFilter DateCell.Column - .Range(1).Column + 1, _
    ">=" & Format(DateSerial(lYear, lMonth, 1), rngCell.Cells(2, 1).NumberFormat), _
    xlAnd, _
    "<=" & Format(DateSerial(lYear, lMonth + 1, 0), rngCell.Cells(2, 1).NumberFormat)
    End With
    End If
    End If
    End If
    End If

    x = Sum_Visible_Cells(rngCol)

    LValue = Format(x, "Currency")

    MsgBox LValue

    Set rng = .Range(.Cells(1, 1), .Cells(LastRow, 4))

    If Not rng Is Nothing Then
    'turn filter off
    .AutoFilterMode = False
    'reset filter
    rng.AutoFilter
    .EnableAutoFilter = True
    End If
    End With

    End Sub

    Function Sum_Visible_Cells(Cells_To_Sum As Object)
    Dim aCell As Range
    Dim total As Double
    Application.Volatile
    For Each aCell In Cells_To_Sum
    If aCell.Rows.Hidden = False Then
    If aCell.Columns.Hidden = False Then
    total = total + aCell.Value
    End If
    End If
    Next
    Sum_Visible_Cells = total
    End Function[/vba]
    ____________________________________________
    Nihil simul inventum est et perfectum

    Abusus non tollit usum

    Last night I dreamed of a small consolation enjoyed only by the blind: Nobody knows the trouble I've not seen!
    James Thurber

  3. #3
    Distinguished Lord of VBAX VBAX Grand Master Bob Phillips's Avatar
    Joined
    Apr 2005
    Posts
    25,453
    Location
    Also, that summation function seems overly-indulgent. Rather than the line to call it

    [vba]
    x = Sum_Visible_Cells(rngCol)[/vba]

    why not just use

    [vba]
    x = Application.Sum(rngCol.SpecialCells(xlCellTypeVisible))[/vba]
    ____________________________________________
    Nihil simul inventum est et perfectum

    Abusus non tollit usum

    Last night I dreamed of a small consolation enjoyed only by the blind: Nobody knows the trouble I've not seen!
    James Thurber

  4. #4
    VBAX Expert
    Joined
    Sep 2010
    Posts
    604
    Location
    Thanks a lot Bob... for both getting the routine working correctly and the explanations.

    Quote Originally Posted by xld
    why not just use
    [vba]
    x = Application.Sum(rngCol.SpecialCells(xlCellTypeVisible))[/vba]
    Yes of course, that is so much simpler. - Not sure why I don't remember commands like that , as I know I've both seen and been supplied with it a few times

    Quote Originally Posted by xld
    Your problem was that the total variable was a long, so each time you accumulated into there, the pennies were lost.
    Awe yes, makes sense. Just another thing that I should know by now.

    Quote Originally Posted by xld
    Firstly, I had to change the autofilter to work here in the UK. AUtofilter with dates is very flaky, and you have to take care.
    Oh ok cool. I'll certainly will use that change as well, to make it more universal.

    In case anyone happens by and wishes to use this, the version below incorporates your changes, plus I modified the sum total message to include the month and year.
    [vba]Private Sub CommandButton1_Click()
    'modified slightly Code found at this link
    'http://www.dailydoseofexcel.com/archives/2008/11/26/autofiltering-on-months/
    'If using a command button, I recommend changing the TakeFocusOnClick property to false
    Dim lMonth As Long, lYear As Long, rngCell As Range, rngCol As Range
    Dim LastRow As Long, wks As Worksheet
    Dim DateCell As Range, rng As Range, x As Double, LValue As String

    Set wks = ActiveSheet
    With wks
    LastRow = ActiveSheet.Range("D" & Rows.Count).End(xlUp).Row

    If ActiveCell.Row = 1 Or ActiveCell.Row > LastRow Then
    MsgBox "Please select a row that has data"
    Exit Sub
    End If

    Set rngCol = ActiveSheet.Range("D2" & LastRow) ' Cost Total Column
    Set rngCell = Range("A2:A" & LastRow) ' Date Column

    Set DateCell = ActiveCell.EntireRow.Cells(1)

    DateCell.Select

    If Not rngCell Is Nothing Then

    If IsDate(DateCell.Value) Then

    lMonth = Month(DateCell.Value)
    lYear = Year(DateCell.Value)

    'Check if there is an autofilter
    If rngCell.Parent.AutoFilterMode Then

    'Make sure DateCell is within autofilter range
    If Not Intersect(DateCell, _
    rngCell.Parent.AutoFilter.Range) Is Nothing Then

    'Create filter
    With rngCell.Parent.AutoFilter

    .Range.AutoFilter DateCell.Column - .Range(1).Column + 1, _
    ">=" & Format(DateSerial(lYear, lMonth, 1), rngCell.Cells(2, 1).NumberFormat), _
    xlAnd, _
    "<=" & Format(DateSerial(lYear, lMonth + 1, 0), rngCell.Cells(2, 1).NumberFormat)
    End With
    End If
    End If
    End If
    End If

    x = Application.Sum(rngCol.SpecialCells(xlCellTypeVisible))

    LValue = "Grand total for " & MonthName(lMonth, False) _
    & ", " & lYear & " is " & Format(x, "Currency")

    MsgBox LValue

    Set rng = .Range(.Cells(1, 1), .Cells(LastRow, 4))

    If Not rng Is Nothing Then
    'turn filter off
    .AutoFilterMode = False
    'reset filter
    rng.AutoFilter
    .EnableAutoFilter = True
    End If
    End With

    End Sub[/vba]

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •