Excel 2010, VBA and ListObjects subtotals not updating on Table changes

最后都变了- 提交于 2019-12-05 05:49:27

There is an outstanding bug in Excel tables, and there are some subtleties that need to be addressed in order to get the outcome you require.

A crude fix using explicit calculation tricks does work, but while this approach will update the totals based on the current values in the data rows, they need to be applied every time there are changed values in the data table.

There are 2 ways to force Excel to calculate the totals:

  1. You can toggle the Calculation state of the parent Worksheet:

    objLO.Parent.EnableCalculation = False
    objLO.Parent.EnableCalculation = True
    
  2. Or, you can replace the = in the totals formulas:

    objLO.TotalsRowRange.Replace "=", "="
    

But neither of the above approaches give you a lasting solution that keeps the totals up to date automatically.

A better solution...

The clue to the solution lies in the fact that subtotals are dynamically calculated for columns that existed when the ListObject was converted from a range to a ListObject.

You can exploit this knowledge, and ensure that instead of appending columns to the end/right of the ListObject, you insert them before an existing column. But as you ultimately want the new columns to be right-most, this approach will require the use of a dummy column in the original range, then all new columns are inserted before the Dummy column, and finally, the Dummy column can be deleted.

See this modified code, with comments:

Function test()

    Dim objLO As ListObject

    'Expand the selection to grab an additional Dummy column
    Set objLO = ActiveSheet.ListObjects.Add(xlSrcRange, Range("$A$1:$E$6"), , xlYes)
    objLO.Name = "Recap"
    objLO.TableStyle = "TableStyleMedium2"

    'Insert all of the new columns BEFORE the Dummy column
    objLO.ListColumns.Add (objLO.ListColumns.Count)
    objLO.HeaderRowRange(objLO.ListColumns.Count - 1) = "Tot1"
    objLO.ListColumns.Add (objLO.ListColumns.Count)
    objLO.HeaderRowRange(objLO.ListColumns.Count - 1) = "Tot2"
    objLO.ListColumns.Add (objLO.ListColumns.Count)
    objLO.HeaderRowRange(objLO.ListColumns.Count - 1) = "Tot3"
    objLO.ListColumns.Add (objLO.ListColumns.Count)
    objLO.HeaderRowRange(objLO.ListColumns.Count - 1) = "Tot4"

    'Must show totals BEFORE applying totals, otherwise the last column defaults to Count (even if we override it)
    objLO.ShowTotals = True

    objLO.ListColumns("Tot1").TotalsCalculation = xlTotalsCalculationSum
    objLO.ListColumns("Tot2").TotalsCalculation = xlTotalsCalculationSum
    objLO.ListColumns("Tot3").TotalsCalculation = xlTotalsCalculationSum
    objLO.ListColumns("Tot4").TotalsCalculation = xlTotalsCalculationSum

    'Remove the extra dummy column
    objLO.ListColumns(objLO.ListColumns.Count).Delete

    'Now toggle the ShowTotals to force the ListObject to recognise the new column totals
    objLO.ShowTotals = False
    objLO.ShowTotals = True

End Function

You are not missing anything. This issue seems to be a bug that Microsoft have not fixed yet.

The only thing you can try by now is to Save/Close/Reopen the workbook by code.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!