Seamlessly update Slicer and PivotTable Cache throughout your workbook with or without using Tables. WE_PivotTable does away with the complexity of Syncing multiple PivotTables and Slicers in just one call that updates Slicers and PivotTable Caches.
AWE_PivotTable also allows you to iterate through each filtered row in your PivotTable using a callback function. This allows you to automatically filter items in your PivotTable and then perform functions like emailing portions of the PivotTable to relevant people.
The below example assumes that you already know how to use PivotTables to summarize, sort, reorganize, group, and aggregate the data stored in your spreadsheet. It also assumes that you know how to use Slicers to concurrently filter multiple pivot tables and graphs within your workbook.
Add the below AWE_PivotTable class to your workbook (see How to Create a Class for more information). Function definitions, parameters and examples are documented in the comments before each function (see below).
'******************************************************************************************************************
'******************************************************************************************************************
'* AWE_PivotTable: Seamlessly update Slicer and PivotTable Cache throughout your workbook with or without **
'* using Tables. WE_PivotTable does away with the complexity of Syncing multiple PivotTables **
'* and Slicers in just one call that updates Slicers and PivotTable Caches. **
'* Author: Mike Libby **
'* Website: AutomationWithExcel.com **
'******************************************************************************************************************
'******************************************************************************************************************
OptionExplicit'--------------------------------------------------------------------------
'--- UpdateCaches: Update all Pivot and Slicer Caches in the Workbook ---
'--------------------------------------------------------------------------
PublicFunctionUpdateCaches(OptionalWBAsWorkbook=Nothing)IfWBIsNothingThenSetWB=ThisWorkbookDimSlcrCacheAsSlicerCache,SlcrNmAsStringDimiPTAsLong,PTAsPivotTable,ParentPTAsPivotTable,PTNmAsVariant,PTCacheAsPivotCache,PTSheetNmAsStringDimiDictAsLongDimSlicerArrDictAsObject:SetSlicerArrDict=CreateObject("Scripting.Dictionary")DimSlicerPTNmDictAsObject:SetSlicerPTNmDict=CreateObject("Scripting.Dictionary")DimiarrAsLong,Arr()AsVariantDimWSAsWorksheet'-----------------------------------------------------------------------------------
'--- Create Dictionary of Slicers whose items contain an array of PivotTables ---
'-----------------------------------------------------------------------------------
'--- Note: The parent PivotTable is the first PivotTable in the PivotTables List ---
'--- and the first array element in the PivotTable array. ---
'--- Children are any PivotTables after the fist PivotTable list and and array. ---
'-----------------------------------------------------------------------------------
ForEachSlcrCacheInWB.SlicerCaches'--- Create the Slicer PivotTable Array ---
ReDimArr(1ToSlcrCache.PivotTables.Count)'--- Iterate each PivotTable in the Workbooks SlicerCache ---
ForiPT=SlcrCache.PivotTables.CountTo1Step-1SetPT=SlcrCache.PivotTables(iPT)'--- Format = SheetNm:PivotTableNm ---
PTSheetNm=PT.Parent.Name&":"&PT.Name'--- Build the array of PivotTables belonging to the Slicer ---
Arr(iPT)=PTSheetNm'--- Add the Sheet and Pivot table to the Dictionary of PivotTables that belong to Slicers ---
SlicerPTNmDict(PTSheetNm)=""'--- Decouple child PivotTables from the Slicer ---
IfiPT>1ThenSlcrCache.PivotTables.RemovePivotTable(PT)NextiPT'--- Add the array of pivot tables belonging to the Slicer to SlicerArrDict.
SlicerArrDict(SlcrCache.Name)=ArrNextSlcrCache'-----------------------------------------------------------------------------------
'--- Update the Parent PivotTable Cache ---
'-----------------------------------------------------------------------------------
'--- Note: All child PivotTables have been decoupled from Slicers (see above). ---
'--- Only parent PivotTables remain whose cache will be updated below. ---
'-----------------------------------------------------------------------------------
ForEachSlcrCacheInWB.SlicerCachesForiPT=SlcrCache.PivotTables.CountTo1Step-1SetPT=SlcrCache.PivotTables(iPT)UpdatePivotCachePT,WBNextiPTNextSlcrCache'-----------------------------------------------------------------------------------
'--- Copy Parent PivotTable Cache to Child PivotTables and rejoin Children to ---
'--- their Slicers. ---
'-----------------------------------------------------------------------------------
ForiDict=0ToSlicerArrDict.Count-1SlcrNm=SlicerArrDict.Keys()(iDict)Arr=SlicerArrDict.Items()(iDict)'--- Get the Slicer ---
SetSlcrCache=WB.SlicerCaches(SlcrNm)'--- Get the Parent PivotTable ---
PTSheetNm=Split(Arr(1),":")(0)PTNm=Split(Arr(1),":")(1)SetParentPT=WB.Sheets(PTSheetNm).PivotTables(PTNm)'--- Copy Parent PivotTable to the Child PivotTables using the Parent PivotTable's CacheIndex ---
IfUBound(Arr)>=2ThenForiarr=2ToUBound(Arr)PTSheetNm=Split(Arr(iarr),":")(0)PTNm=Split(Arr(iarr),":")(1)SetPT=WB.Sheets(PTSheetNm).PivotTables(PTNm)PT.CacheIndex=ParentPT.CacheIndexPT.RefreshTable'--- Rejoin the Slicer's PivotTables ---
SlcrCache.PivotTables.AddPivotTablePTNextiarrEndIfNextiDict'-----------------------------------------------------------------------------------
'--- Update all non-Slicer cache ---
'-----------------------------------------------------------------------------------
'--- Note: Iterate all worksheets and update pivot table cache that is not in ---
'--- defined in the SlicerPTNmDict. ---
'-----------------------------------------------------------------------------------
ForEachWSInWB.SheetsForEachPTInWS.PivotTablesPTSheetNm=WS.Name&":"&PT.NameIfNotSlicerPTNmDict.Exists(PTSheetNm)ThenCallUpdatePivotCache(PT,WB)EndIfNextPTNextWSEndFunction'--------------------------------------------------------------------------
'--- UpdatePivotCache: Update a PivotTable's cache in the Workbook ---
'--------------------------------------------------------------------------
PublicFunctionUpdatePivotCache(PTAsPivotTable,OptionalWBAsWorkbook=Nothing)IfWBIsNothingThenSetWB=ThisWorkbookDimWSAsWorksheet'--- Sheets ---
DimsheetnmAsString,LastRowAsLong,strRngAsString,SrcRngAsRangeWithPTIfInStr(PT.SourceData,"!")>0Thensheetnm=Left(PT.SourceData,InStr(PT.SourceData,"!")-1)SetWS=WB.Sheets(sheetnm)LastRow=GetLastRow(WS)strRng=Application.ConvertFormula(PT.SourceData,xlR1C1,xlA1)strRng=Left(strRng,InStrRev(strRng,"$"))&CStr(LastRow).ChangePivotCacheWB.PivotCaches.Create(_SourceType:=xlDatabase,_SourceData:=WS.Range(strRng)_)EndIf.RefreshTable.SaveData=True.UpdateEndWithEndFunction'--------------------------------------------------------------------------
'--- ClearSlicerFilters: Clear all Slicer Filters in the Workbook ---
'--------------------------------------------------------------------------
PublicFunctionClearSlicerFilters(OptionalWBAsWorkbook=Nothing)IfWBIsNothingThenSetWB=ThisWorkbookDimSlcrCacheAsSlicerCacheForEachSlcrCacheInWB.SlicerCachesIfSlcrCache.FilterCleared=FalseThenSlcrCache.ClearManualFilterNextSlcrCacheEndFunction'--------------------------------------------------------------------------
'--- UnlockSlicers: Unlock all Slicers in the Workbook ---
'--------------------------------------------------------------------------
PublicFunctionUnlockSlicers(OptionalWBAsWorkbook=Nothing)IfWBIsNothingThenSetWB=ThisWorkbookDimSCAsSlicerCache,SLCRAsSlicerForEachSCInWB.SlicerCachesForEachSLCRInSC.SlicersSLCR.Locked=FalseNextSLCRNextSCEndFunction'--------------------------------------------------------------------------
'--- ForEachPivotTableFilterItem: Perform the following:
'--- 1) Filter the PivotTable
'--- 2) Iterate each row
'--- 3) Perform a callback
'--------------------------------------------------------------------------
PublicFunctionForEachPivotTableFilterItem(PTAsPivotTable,CallBackFuncAsString,ColNmToFilterAsString)DimPFAsPivotField:SetPF=PT.PivotFields(ColNmToFilter)DimPIAsPivotItem,PI2AsPivotItem,PRAsRangeDimWSAsWorksheet:SetWS=PT.ParentDimFilterValAsVariant,FilterValsAsStringDimiPIAsLong'--- Get an array of unique filtered items ---
DimArr()AsVariant:Arr=GetPivotFilterValues(PT,ColNmToFilter)'--- Iterate through each unique filtered item and perform the callback function ---
ForEachFilterValInArrPivotTableFilterByPT,ColNmToFilter,CStr(FilterVal),TrueIfPT.DataBodyRange.Rows.Count>=2ThenIfFilterVals<>""ThenFilterVals=FilterVals&";"FilterVals=FilterVals&CStr(FilterVal)Application.RunCallBackFunc,PTEndIfNextFilterVal'--- Reset the original filtered values ---
PF.ClearAllFiltersOnErrorResumeNextWithPT.PivotFields(ColNmToFilter)ForiPI=1To.PivotItems.Count.PivotItems(iPI).Visible=FalseForEachFilterValInArrIf.PivotItems(iPI)=FilterValThen.PivotItems(iPI).Visible=TrueNextFilterValNextiPIEndWithOnErrorGoTo0EndFunction'--------------------------------------------------------------------------
'--- GetPivotFilterValues: Return an array of Pivot Filers and Values ---
'--------------------------------------------------------------------------
PublicFunctionGetPivotFilterValues(PTAsPivotTable,ColNmToFilterAsString)AsVariantDimPFAsPivotField:SetPF=PT.PivotFields(ColNmToFilter)DimVisPIsAsPivotItems:SetVisPIs=PF.VisibleItemsDimVisPIAsPivotItem,PRAsRangeDimWSAsWorksheet:SetWS=PT.ParentDimArr()AsVariant,iarrAsLong'--- Return empty array if there are no visible items ---
IfVisPIs.Count=0ThenGetPivotFilterValues=Array()ElseReDimArr(VisPIs.Count-1)Foriarr=0ToVisPIs.Count-1SetVisPI=VisPIs(iarr+1)Arr(iarr)=VisPI.ValueNextiarrGetPivotFilterValues=ArrEndIfEndFunction'--------------------------------------------------------------------------
'--- PivotTableFilterBy: Filter a PivotTable ---
'--------------------------------------------------------------------------
PublicFunctionPivotTableFilterBy(PTAsPivotTable,ColNmToFilterAsString,FilterValueAsString,OptionalClearFiltersAsBoolean=True)DimPFAsPivotField,PIAsPivotItem,PI2AsPivotItem,PRAsRangeDimWSAsWorksheet:SetWS=PT.ParentSetPF=PT.PivotFields(ColNmToFilter)IfClearFilters=TrueThenPF.ClearAllFiltersPF.PivotFilters.Add2xlCaptionEquals,,FilterValueEndFunction'--------------------------------------------------------------------------
'--- SlicerFilterBy: Filter a Slicer ---
'--------------------------------------------------------------------------
PublicFunctionSlicerFilterBy(SlcrCacheNmAsString,FilterValueAsString,OptionalWBAsWorkbook=Nothing)IfWBIsNothingThenSetWB=ThisWorkbookDimSCAsSlicerCache:SetSC=WB.SlicerCaches(SlcrCacheNm)DimSIAsSlicerItemSC.ClearAllFiltersForEachSIInSC.SlicerItemsIfSI.Caption=FilterValueThenSI.Selected=TrueElseSI.Selected=FalseEndIfNextSIEndFunction'--------------------------------------------------------------------------
'--- PivotTableRange: Retrieve the range of the Pivot Table including ---
'--- columns to the right of the Pivot Table. ---
'--------------------------------------------------------------------------
PublicFunctionPivotTableRange(PTAsPivotTable)AsRangeDimWSAsWorksheet:SetWS=PT.ParentDimFrAddrAsString:FrAddr=Split(PT.TableRange1.Address,":")(0)DimFrRowAsLong:FrRow=CLng(Split(FrAddr,"$")(2))DimFrColAsLong:FrCol=PT.TableRange1.ColumnDimToAddrAsString:ToAddr=Split(PT.TableRange1.Address,":")(1)DimToRowAsLong:ToRow=CLng(Split(ToAddr,"$")(2))DimToColAsLong:ToCol=WS.UsedRange.Columns.CountSetPivotTableRange=WS.Range(FrAddr,WS.Cells(ToRow,ToCol))EndFunction'--------------------------------------------------------------------------
'--- PivotTableHdrRange: Retrieve the Pivot Table's header range ---
'--- including columns to the right of the ---
'--- PivotTable. ---
'--------------------------------------------------------------------------
PublicFunctionPivotTableHdrRange(PTAsPivotTable)AsRangeDimWSAsWorksheet:SetWS=PT.ParentDimFrAddrAsString:FrAddr=Split(PT.TableRange1.Address,":")(0)DimFrRowAsLong:FrRow=CLng(Split(FrAddr,"$")(2))DimFrColAsLong:FrCol=PT.TableRange1.ColumnDimToAddrAsString:ToAddr=Split(PT.TableRange1.Address,":")(1)DimToRowAsLong:ToRow=CLng(Split(ToAddr,"$")(2))DimToColAsLong:ToCol=WS.UsedRange.Columns.CountSetPivotTableHdrRange=WS.Range(WS.Cells(FrRow,FrCol),WS.Cells(FrRow,ToCol))EndFunction'--------------------------------------------------------------------------
'--- PivotTableLastRow: Retrieve the Pivot Table's last row ---
'--------------------------------------------------------------------------
PublicFunctionPivotTableLastRow(PTAsPivotTable)AsLongWithPT.TableRange2PivotTableLastRow=.Rows(.Rows.Count).RowEndWithEndFunction'--------------------------------------------------------------------------
'--- PivotTableFirstRow: Retrieve the Pivot Table's first row ---
'--------------------------------------------------------------------------
PublicFunctionPivotTableFirstRow(PTAsPivotTable)AsLongDimFrAddrAsString:FrAddr=Split(PT.TableRange1.Address,":")(0)PivotTableFirstRow=CLng(Split(FrAddr,"$")(2))+1EndFunction'--------------------------------------------------------------------------
'--- PivotTableHdrRow: Retrieve the Pivot Table's HdrRow ---
'--------------------------------------------------------------------------
PublicFunctionPivotTableHdrRow(PTAsPivotTable)AsLongDimFrAddrAsString:FrAddr=Split(PT.TableRange1.Address,":")(0)PivotTableHdrRow=CLng(Split(FrAddr,"$")(2))EndFunction'--------------------------------------------------------------------------
'--- PivotTableLastCol: Retrieve the Pivot Table's LastRow ---
'--------------------------------------------------------------------------
PublicFunctionPivotTableLastCol(PTAsPivotTable,OptionalIsExtendedAsBoolean=False)AsLongPivotTableLastCol=PivotTableRange(PT).Columns.CountEndFunction'--------------------------------------------------------------------------
'--- GetLastRow: Get the last row for the worksheet ---
'--------------------------------------------------------------------------
PrivateFunctionGetLastRow(WSAsWorksheet)AsLongGetLastRow=WS.UsedRange.Rows.CountEndFunction'--------------------------------------------------------------------------
'--- GetLastCol: Get the last column for the worksheet ---
'--------------------------------------------------------------------------
PrivateFunctionGetLastCol(WSAsWorksheet)AsLongGetLastCol=WS.UsedRange.Columns.CountEndFunction
AWE_PivotTable Examples
Update All Pivot Tables and Slicers in a Workbook
Sub btnRefreshPivotTables_Click()
Dim AWE_PT As New AWE_Pivot
AWE_PT.UpdateCaches
End Sub
Perform a Callback for Each Filter Item
Public Sub btnRevDetails_Click()
Dim WS As New Worksheet: Set WS = ThisWorkbook.Sheets("Dashboard")
Dim AWE_PT As New AWE_Pivot
Dim PT As PivotTable: Set PT = WS.PivotTables("PT_Employees")
Perform a Callback Function For Each Filtered Item in the PivotTable
Dim WS As Worksheet: Set WS = ThisWorkbook.Sheets("Sheet1")
Dim PT As PivotTable: Set PT = WS.PivotTables("PT_Employees")
AWE_PT.ForEachPivotTableFilterItem PT, "Sheet1.CallbackFunc", "FilteredColNm"
Public Sub CallbackFunc (PT As PivotTable)
With PT
EmpNm = .TableRange1.Cells(2, .PivotFields("FilteredColNm ").Position).Value
Debug.Print "Employee Name: " & EmpNm
Debug.Print "Entire Pivot Table:" & .TableRange1.Address
Debug.Print "-----------------------------------"
End With
End Sub
Add comment
Comments