【问题标题】:VBA Excel file size containing multiple pivot tables is huge包含多个数据透视表的 VBA Excel 文件大小很大
【发布时间】:2018-11-19 04:30:07
【问题描述】:

我正在自动化在 Excel 中创建数据透视表的过程。我遇到的问题是我使用宏创建的数据透视表比我手动创建的数据透视表大得多。两个数据透视表看起来相同,但文件大小有很大差异。

如上图所示,由我的宏创建的宏大约大 6 倍!我怀疑这是我在创建数据透视表时缓存数据的方式。所以,这是我用来创建数据透视表的通用代码。

Sub pivottable1()

    Dim PSheet As Worksheet, DSheet As Worksheet
    Dim PCache As PivotCache
    Dim PTable As PivotTable
    Dim PField As PivotField
    Dim PRange As Range
    Dim LastRow As Long
    Dim LastCol As Long
    Dim PvtTable As PivotTable
    Dim SheetName As String
    Dim PTName As String

    SheetName = "MySheetName1"
    PTName = "PivotTable1"
    On Error Resume Next
    Application.DisplayAlerts = False
    Worksheets(SheetName).Delete
    Sheets.Add After:=ActiveSheet
    ActiveSheet.Name = SheetName
    Application.DisplayAlerts = True

    Set PSheet = Worksheets(SheetName)
    Set DSheet = Worksheets(1)

    LastRow = DSheet.Cells(Rows.Count, 1).End(xlUp).Row
    LastCol = DSheet.Cells(1, Columns.Count).End(xlToLeft).Column
    Set PRange = DSheet.Cells(1, 1).Resize(LastRow, LastCol)

    Set PCache = ActiveWorkbook.PivotCaches.Create _
    (SourceType:=xlDatabase, SourceData:=PRange). _
    CreatePivotTable(TableDestination:=PSheet.Cells(4, 1), _
    TABLENAME:=PTName)

    Set PTable = PCache.CreatePivotTable _
    (TableDestination:=PSheet.Cells(1, 1), TABLENAME:=PTName)

    Sheets(SheetName).Select
        Set PvtTable = ActiveSheet.PivotTables(PTName)
        'Rows
        With PvtTable.PivotFields("TypeCol")
            .Orientation = xlRowField
            .Position = 1
        End With

        With PvtTable.PivotFields("NameCol")
            .Orientation = xlRowField
            .Position = 2
        End With

        'Columns
        With PvtTable.PivotFields("CategoryCol")
            .Orientation = xlColumnField
            .Position = 1
        End With

        'Values
        PvtTable.AddDataField PvtTable.PivotFields("Values1"), "Value Balance", xlSum
        PvtTable.AddDataField PvtTable.PivotFields("Values2"), "Value 2 Count", xlCount

        With PvtTable
            .PivotFields("TypeCol").ShowDetail = False
            .TableRange1.Font.Size = 10
            .ColumnRange.HorizontalAlignment = xlCenter
            .ColumnRange.VerticalAlignment = xlTop
            .ColumnRange.WrapText = True
            .ColumnRange.Columns.AutoFit
            .ColumnRange.EntireRow.AutoFit
            .RowAxisLayout xlTabularRow
            .ShowTableStyleRowStripes = True
            .PivotFields("TypeCol").AutoSort xlDescending, "Value Balance" 'Sort descdending order
            .PivotFields("NameCol").AutoSort xlDescending, "Value Balance"
        End With

        'Change Data field (Values) number format to have thousand seperator and 0 decimal places.
        For Each PField In PvtTable.DataFields
            PField.NumberFormat = "#,##0"
        Next PField

End Sub

这就是我如何创建 6 个不同的数据透视表,它们都使用位于同一工作簿中且位于该工作簿的第一个工作表中的相同数据源。因此,例如,我的第二个数据透视表宏代码看起来像这样。

Sub pivottable2()

    Dim PSheet As Worksheet, DSheet As Worksheet
    Dim PCache As PivotCache
    Dim PTable As PivotTable
    Dim PField As PivotField
    Dim PRange As Range
    Dim LastRow As Long
    Dim LastCol As Long
    Dim PvtTable As PivotTable
    Dim SheetName As String
    Dim PTName As String

    SheetName = "MySheetName2"
    PTName = "PivotTable2"
    On Error Resume Next
    Application.DisplayAlerts = False
    Worksheets(SheetName).Delete
    Sheets.Add After:=ActiveSheet
    ActiveSheet.Name = SheetName
    Application.DisplayAlerts = True

    Set PSheet = Worksheets(SheetName)
    Set DSheet = Worksheets(1)

    LastRow = DSheet.Cells(Rows.Count, 1).End(xlUp).Row
    LastCol = DSheet.Cells(1, Columns.Count).End(xlToLeft).Column
    Set PRange = DSheet.Cells(1, 1).Resize(LastRow, LastCol)

    Set PCache = ActiveWorkbook.PivotCaches.Create _
    (SourceType:=xlDatabase, SourceData:=PRange). _
    CreatePivotTable(TableDestination:=PSheet.Cells(4, 1), _
    TABLENAME:=PTName)

    Set PTable = PCache.CreatePivotTable _
    (TableDestination:=PSheet.Cells(1, 1), TABLENAME:=PTName)

    Sheets(SheetName).Select
        Set PvtTable = ActiveSheet.PivotTables(PTName)
        'Rows
        With PvtTable.PivotFields("ManagerCol")
            .Orientation = xlRowField
            .Position = 1
        End With

        With PvtTable.PivotFields("IDCol")
            .Orientation = xlRowField
            .Position = 2
        End With

        'Columns
        With PvtTable.PivotFields("CategoryCol")
            .Orientation = xlColumnField
            .Position = 1
        End With

        'Values
        PvtTable.AddDataField PvtTable.PivotFields("Values1"), "Value Balance", xlSum

End Sub

我只更改宏名称、工作表名称、数据透视表名称和数据透视表的输入行/列/数据值。

我希望完成的是将宏创建的数据透视表的文件大小减小到类似于我手动创建的数据。

如果你们还有什么想知道的,欢迎评论。我将对问题进行编辑并分别添加详细信息。

【问题讨论】:

  • 可能是 VBA 本身导致代码如此之大,如果您将代码放在 WorkBook_Macro 中并将代码工作簿中的代码运行到数据工作簿中,您将设法缩小尺寸?因为现在的方式我强烈建议您不要使用该代码(但无论如何都要感谢您发布它!)
  • @HilaDG “可能是 VBA 本身导致代码变得那么大”不太清楚你的意思是什么,但我很确定这是我为枢轴缓存数据的方式创建它们时会导致文件大小有如此大差异的表。我使用的代码是我认为在互联网上构建数据透视表的最常用方法。它为每个数据透视表创建一个单独的缓存,而不是在彼此之间共享它们。我想知道,我将如何重新调整代码,以便我创建的数据透视表都共享相同的数据缓存? :)
  • 看起来您的代码为每个 Sub 创建了两个可枢转数据 - 一个在 A4,一个在 A1 - 这是故意的吗?您可以只创建一个数据透视缓存并将每个数据透视表指向该缓存 - 您尝试过吗?
  • @TimWilliams “看起来您的代码为每个 Sub 创建了两个可枢转对象”哦,不错。那是我的一个错误。我排除了在不同位置创建另一个数据透视表的两行额外代码。但是,这对文件大小没有任何影响。 “您可以只创建一个数据透视缓存并将每个数据透视表指向该缓存”,我将如何做到这一点?我是否必须将这两个宏都包含在新的子例程中,以便它们能够共享相同的缓存?
  • @DSM 我的意思是代码本身占用了一些空间,这可能就是为什么(在下面发布的答案中)手动版本和自动版本之间存在细微差别。顺便说一句,请接受下面的答案,因为它看起来是正确的。

标签: excel vba


【解决方案1】:

您可以对多个数据透视表使用相同的数据透视缓存(假设它们基于相同的源数据)。

未经测试:

'creates and returns a shared pivotcache object
Function GetPivotCache() As PivotCache
    Static pc As PivotCache 'static variables retain their value between calls
    Dim pRange As Range

    If pc Is Nothing Then 'create if not yet created
        Set prRange = Worksheets(1).Range("A1").CurrentRegion
        Set pc = ActiveWorkbook.PivotCaches.Create _
                     (SourceType:=xlDatabase, SourceData:=pRange)
    End If
    Set GetPivotCache = pc
End Function


Sub pivottable1()

    '...
    '...

    Set PSheet = Worksheets(SheetName)

    Set PCache = GetPivotCache() '<<< will be created if needed

    Set PTable = PCache.CreatePivotTable _
                   (TableDestination:=PSheet.Cells(1, 1), TableName:=PTName)

    '...
    '...

End Sub

【讨论】:

  • 哦,看来您已经分享了答案!我会尝试并尽快回复您。
  • 我已将代码应用到我的宏中。我很高兴地说,尺寸已大大减小到几乎与手动尺寸相同!我有一个关于 GetPivotCache 函数和静态变量的问题,因为我不熟悉它的工作原理。可以说,我创建了 6 个数据透视表,它们使用工作表 1 中的数据作为该线程问题的结构。如果我有另一个使用工作表 2 中的数据的 6 个数据透视表怎么办。我将无法对接下来的 6 个数据透视表使用相同的函数,因为数据透视缓存存储工作表 1 的数据,对吧?
  • 是的 - 目前在该函数中定义了一个特定范围。您可以复制它并更改副本中的范围,或者可以创建一个函数,您可以将要使用的源范围传递给该函数,但这可能比您需要的要复杂一些...... .
  • “可以创建一个函数,您可以将要使用的源范围传递给该函数”,我确实对您的答案进行了一些更改,以便 GetPivotCache 函数接受数据范围,因此不必在函数本身中定义。如果我们要使用单个函数,是否必须检查数据范围是否不同才能创建新缓存?我同意这不仅仅是问题所要求的,因为我构建了它来捕捉问题的基础。我应该在一个新问题中问这个吗?
【解决方案2】:

我以前见过这种行为。正如您现在所看到的,由于创建 Pivots 的本质,您的 WB 会膨胀。过去我使用 VBA 创建 Pivots,就像您正在做的那样,然后在最后运行一个小脚本来复制所有内容,并粘贴特殊值。这将消除大部分,也许是所有的膨胀。此外,不要将您的 WB 保存为 XLSX,而是尝试使用 XLSB,它比 XLSX 小 4 倍左右,并且打开/关闭速度比 XLSX 快 4 倍左右。我想知道你为什么还要使用 XLSX,因为你不能以那种格式保存宏。或者,也许您有一个可以完成所有工作的模板 WB,您只需将新报告保存为 XLSX。不管怎样,从现在开始考虑使用 XLSB 格式。

【讨论】:

  • 您好! “我想知道你为什么还要使用 XLSX,因为你不能以那种格式保存宏。”你说的对。我将我的宏保存在一个 excel 添加文件中,以便宏在任何打开的工作簿中运行。 “一个复制所有并粘贴特殊值的小脚本”,起初我确实认为这是一个选项,但由于我手动执行文件大小相当大,我想寻找方法将数据透视表保持为是,但文件大小也接近手动完成时可实现的大小。
  • 我怀疑这是我缓存用于数据透视表的数据的方式,这让我提出了这个问题,即如何在不同的数据透视表之间共享相同的缓存数据。有时我有 2-3 个不同的数据源,其中 20-24 个数据透视表来自这些数据源。为 20 个数据透视表创建单独的缓存会很疯狂! @Tim Williams 提供的答案正是我所需要的,但是由于数据工作表中的更新或只是使用具有自己不同数据的不同工作表,数据范围会发生变化。 Tim 的解决方案适用于单个数据缓存。我会尝试使用 XLSB 格式!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-11
  • 1970-01-01
  • 2023-02-26
相关资源
最近更新 更多