Select/Deselect all Pivot Items

10.3k Views Asked by At

I have a pivot table, and I am trying to select certain pivot items based on values in an array. I need this process to go faster, so I have tried using Application.Calculation = xlCalculationManual and PivotTables.ManualUpdate = True, but neither seem to be working; the pivot table still recalculates each time I change a pivot item.

Is there something I can do differently to prevent Excel from recalculating each time? Or is there a way to deselect all items at once (not individually) to make the process go quicker?

Here is my code:

Application.Calculation = xlCalculationManual

'code to fill array with list of companies goes here    

Dim PT As Excel.PivotTable
Set PT = Sheets("LE Pivot Table").PivotTables("PivotTable1")

Sheets("LE Pivot Table").PivotTables("PivotTable1").ManualUpdate = True
Dim pivItem As PivotItem

'compare pivot items to array.  
'If pivot item matches an element of the array, make it visible=true, 
'otherwise, make it visible=false
For Each pivItem In PT.PivotFields("company").PivotItems
    pivItem.Visible = False 'initially make item unchecked
    For Each company In ArrayOfCompanies()
        If pivItem.Value = company Then
            pivItem.Visible = True
        End If
    Next company
Next pivItem
2

There are 2 best solutions below

0
On

It seems unavoidable to have the pivotable refreshed every time a pivotitem is updated. However I tried approaching the problem from the opposite angle. i.e.:

1.Validating the “PivotItems to be hidden” before updating the pivottable.

2.Also making make all items visible at once instead of “initially make item unchecked” one by one.

3.Then hiding all the items not selected by the user (PivotItems to be hidden)

I ran a test with 6 companies selected out of a total of 11 and the pivottable was updated 7 times

Ran also your original code with the same situation and the pivottable was updated 16 times Find below the code

Sub Ptb_ShowPivotItems(aPtbItmSelection As Variant)

Dim oPtb As PivotTable
Dim oPtbItm As PivotItem
Dim aPtbItms() As PivotItem
Dim vPtbItm As Variant
Dim bPtbItm As Boolean
Dim bCnt As Byte

    Set oPtb = ActiveSheet.PivotTables(1)

    bCnt = 0
    With oPtb.PivotFields("Company")

        ReDim Preserve aPtbItms(.PivotItems.Count)
        For Each oPtbItm In .PivotItems

            bPtbItm = False
            For Each vPtbItm In aPtbItmSelection
                If oPtbItm.Name = vPtbItm Then
                    bPtbItm = True
                    Exit For
            End If: Next

            If Not (bPtbItm) Then
                bCnt = 1 + bCnt
                Set aPtbItms(bCnt) = oPtbItm
            End If

        Next
        ReDim Preserve aPtbItms(bCnt)

        .ClearAllFilters
        For Each vPtbItm In aPtbItms
            vPtbItm.Visible = False
        Next

    End With

End Sub
0
On

It seems that you really want to try something different to significantly reduce the time it takes to select the required items in pivotttable. I propose to use a “MirrorField”, i.e. a copy of the “Company” to be used to set in the sourcedata of the pivottable the items you need to hide\show.

First you need to add manually (or programmatically) the “MirrorField” and named same as the source field with a special character at the beginning like “!Company” the item must be part of the sourcedata and it can be placed in any column of it (as this will a “programmer” field I would place it in the last column and probably hidden as to not creating any issues for\with the users)

Please find below the code to update the pivottable datasource and to refresh the pivottable

I’m also requesting the PivotField to be updated just make it flexible as it then can be used for any field (provided that the “FieldMirror” is already created) Last: In case you are running any events in the pivottable worksheet they should be disable and enable only to run with the last pivottable update

Hope this is what you are looking for.

Sub Ptb_ShowPivotItems_MirrorField(vPtbFld As Variant, aPtbItmSelection As Variant)
Dim oPtb As PivotTable
Dim rPtbSrc As Range
Dim iCol(2) As Integer
Dim sRC(2) As String
Dim sFmlR1C1 As String
Dim sPtbSrcDta As String

    Rem Set PivotTable & SourceData
    Set oPtb = ActiveSheet.PivotTables(1)
    sPtbSrcDta = Chr(34) & oPtb.SourceData & Chr(34)
    Set rPtbSrc = Evaluate("=INDIRECT(" & sPtbSrcDta & ",0)")

    Rem Get FieldMirrow Position in Pivottable SourceData (FieldMirrow Already present SourceData)
    With rPtbSrc
        iCol(1) = -1 + .Column + Application.Match(vPtbFld, .Rows(1), 0)
        iCol(2) = Application.Match("!" & vPtbFld, .Rows(1), 0)
    End With

    Rem Set FieldMirror Items PivotTable SourceData as per User Selection
    sRC(1) = """|""&RC" & iCol(1) & "&""|"""
    sRC(2) = """|" & Join(aPtbItmSelection, "|") & "|"""
    sFmlR1C1 = "=IF(ISERROR(SEARCH(" & sRC(1) & "," & sRC(2) & ")),""N/A"",""Show"")"
    With rPtbSrc.Offset(1).Resize(-1 + rPtbSrc.Rows.Count).Columns(iCol(2))
        .Value = "N/A"
        .FormulaR1C1 = sFmlR1C1
        .Value = .Value2
    End With

    Rem Refresh PivotTable & Select FieldMirror Items
    With oPtb

        Rem Optional: Disable Events - In case you are running any events in the pivottable worksheet
        Application.EnableEvents = False

        .ClearAllFilters
        .PivotCache.Refresh
        With .PivotFields("!" & vPtbFld)
            .Orientation = xlPageField
            .EnableMultiplePageItems = False

            Rem Optional: Enable Events - To triggrer the pivottable worksheet events only with last update
            Application.EnableEvents = True
            .CurrentPage = "Show"

    End With: End With

End Sub