VBA column width update for Pivot table refresh - vba

I have a pivot table and a slicer and I need a code that will update the width of each column to fit the value every single time I update the slicer (which updates the pivot). I know that if I got to Pivot table > options, I cant select a box that says "autofit column widths on update", but it doesn't work. So instead I'm trying to make a code that automatically does that.
I tried this:
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
Dim pt As PivotTable
For Each pt In ActiveSheet.PivotTables
columns.autofit
Next pt
End Sub
Something doesn't work though and I'm not sure what it is. Can anybody see an issue with the code? Thank you!

In order to modify the columns width in a PivotTable, you need to address the pt.TableRange1.Columns property.
Try the code below:
Dim pt As PivotTable
For Each pt In ActiveSheet.PivotTables
pt.TableRange1.Columns.AutoFit
Next pt

Related

How to link cell value as a filter in PowerPivot Pivot Table in Excel?

I have two Pivot Table (PivotTable1 and PivotTable2) in Sheet PivotTables_Sheetand a cell that shows the year in Sheet YearInput. I tried to link the cell year (J4) in YearInput as a filter to all pivot tables in PivotTables Sheet.
But somehow my code doesn't work as expected. Anybody knows how to correct this code?
This is the code:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Target.Address = Range("J4").Address Then Exit Sub
Dim pt As PivotTable
Dim ptItem As PivotItem
On Error Resume Next
For Each pt In Worksheets("PivotTables_Sheet").PivotTables
With pt.PivotFields("Year for Sales")
If .EnableMultiplePageItems = True Then
.ClearAllFilters
End If
Set ptItem = .PivotItems(Target.Value)
If Not ptItem Is Nothing Then
.CurrentPage = Target.Value
End If
End With
Next
End Sub
Note: I use Excel 2010 and built the pivot tables using PowerPivot.
One way to do this without VBA is to use a slicer which is common between all the pivots. Then one year is changed on one, it will also update the other pivot tables.
This is by first clicking on the pivot, which will then show on the ribbon an Analyze option. Under that there is an insert slicer, which you would do for year.
Afterwards you would go to your other pivots and instead do filter connection, and select your year slicer.
Note that the year slicer can then just be moved to a hidden sheet if you do not want the end user to see it, it will still do its job of propagating the year across all the pivots that are referencing it.

Trying to use VBA to filter my Pivot Table based on Year and Period values in cells D2 and E2

I am trying to filter my Pivot Table using VBA so it will filter based on a Period and a Year in cells D2 and E2 respectively. I have the below code which is to filter by the year and works without having the Fiscal Period in the Columns but when I put the Fiscal Period in the columns it debugs at the Field.ClearAllFilters and Field.CurrentPage = Year lines. Can someone please help me find a fix for this?
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
If Intersect(Target, Worksheets("CY PT").Range("E2")) Is Nothing Then Exit Sub
Dim PT As PivotTable
Dim Field As PivotField
Dim Year As String
Set PT = Worksheets("CY PT").PivotTables("CY PT")
Set Field = PT.PivotFields("Fiscal Year")
Year = Worksheets("CY PT").Range("E2").Value
With PT
Field.ClearAllFilters
Field.CurrentPage = Year
PT.RefreshTable
End With
End Sub
The .CurrentPage method only applies to PageFields. Sounds like you are trying to filter RowFields. So your options are:
Change your fields to be PageFields; or
Use a Slicer; or
Use a PageField filter dropdown mascarading as a Data Validation
dropdown (like I outline at
http://dailydoseofexcel.com/archives/2014/08/16/sync-pivots-from-dropdown/
); or
Iterate through the PivotItems collection for each field, and set the
.Visible status of everything but the selected items to FALSE.
If you choose the last option, you need to be aware this can take a while. See the code I posted at Filtering a Pivot Table Based on Variable Range to get an understanding of how to do this efficiently. Also give my post at http://dailydoseofexcel.com/archives/2013/11/14/filtering-pivots-based-on-external-ranges/ a read.

Run time error -2147024809 (80070057) - Pivot Table field name is not valid

Got another Excel VBA Macro button issue.
I am trying to make a button to refresh all pivots on a worksheet (there are four). I have been to StackOverflow before and received a solution that worked well. I took the code I was provided before and updated it for the new workbook but it fails below with the function .ChangePivotCache PvtCache:
Sub Button1_Click()
Dim PvtTbl As PivotTable
Dim PvtCache As PivotCache
Dim PvtDataRng As Range
Set PvtDataRng = Worksheets("OTR_Promo_List_ADV_2017").Range("B2:AU500")
Set PvtCache = ActiveWorkbook.PivotCaches.Add(xlDatabase, PvtDataRng)
Set PvtTbl = Worksheets("Desired_Distribution").PivotTables("PivotTable1")
For Each PvtTbl In Worksheets("Desired_Distribution").PivotTables
Set PvtCache = ActiveWorkbook.PivotCaches.Add(xlDatabase, PvtDataRng)
With PvtTbl
.ChangePivotCache PvtCache
.RefreshTable
End With
Set PvtCache = Nothing
Next PvtTbl
End Sub
The only differences are that the workbook changed and now I want to refresh 4 pivots instead of 2 - could that be the issue?
Below a screenshot so you can see the worksheets. "OTR_Promo_List_ADV-2017" is the database. The Pivot tables have the default naming, I did not change the names (i.e. PivotTable1, PivotTable2...)
Thanks!
The code you use to refresh all pivot tables on the one sheet seems overly complex. I don't quite understand why you would want to use .ChangePivotCache at all. It changes the data source of the specified pivot table. If you just want to refresh a pivot table, that is completely unwarranted.
You can use Excel Table objects as the data source for your pivot tables, then a simple refresh will suffice. Or, if you don't want to use Tables (though you may really want to look into that, for obvious reasons), you can use dynamic range names to define the pivot source. With both techniques, you only need to refresh the pivot table and don't have to manipulate the pivot cache with VBA.
With Tables or dynamic range names as the source of pivot tables, you can refresh all pivot tables on a sheet by cycling through them and refresh them with codes along these lines:
Sub RefreshPivotsOnSheet()
Dim ws As Worksheet
Dim pt As PivotTable
Set ws = Worksheets("MySheet")
For Each pt In ws.PivotTables
pt.RefreshTable
Next pt
End Sub
Edit: How to set Excel Tables as the data source for a pivot: Turn the source data into a table with Ctrl + T or Insert > Table. Then edit the Pivot Table data source and point it to the Excel table you just created.
I was able to close this topic. I found somewhere else a simple macro that says only:
Sub REFRESH()
'
' REFRESH Macro
'
'
ActiveWorkbook.RefreshAll
End Sub
seemed to do the trick.
Thank you for all your inputs!

Invalid Procedure Call Or Argument - attempting to dynamically change pivot cache

I'm trying to dynamically refresh some pivot tables in Excel. The pivot tables (and connected slicers - each slicer connects to multiple pivots) already exist, the underlying source data table does not. The process is as follows:
Create new sheet to hold the 'raw' data
Populate sheet, wrap data into a ListObject (table)
Create a new pivot cache from the new data
Unlink the slicers from the pivot tables
Change the pivot tables' cache to the new cache
Refresh the pivot tables
Link the slicers back up
Delete the data sheet
To clarify the structure:
One data source table. Multiple pivot tables pointing to the source. Multiple slicers, each connected to all the pivot tables (eg Week Ending slicer chages Week Ending on all the pivots)
I'm running into a problem however with step 4. The following code works:
'dataTable is a ListObject that was created on a sheet earlier in the function. Can confirm 100% that it exists and is populated.
Dim pt As PivotTable
For Each pt in PivotSheet.PivotTables
pt.ChangePivotCache ThisWorkbook.PivotCaches.Create( _
SourceType:=xlDatabase, _
SourceData:=dataTable)
Next pt
However, it means one pivot cache per pivot table, which means I run into problems when trying to set up slicers that manipulate multiple pivots - it assumes that each pivot table has a different data source, and so will only let me link the slicer to a single pivot.
I decided the way to go would be to create a single pivot cache, and then link each pivot table to it. This code however does not work, throwing error 5 at me the first time it is reached:
'dataTable is a ListObject that was created on a sheet earlier in the function. Can confirm 100% that it exists and is populated.
Dim pc As PivotCache
Set pc = ThisWorkbook.PivotCaches.Create( _
SourceType:=xlDatabase, _
SourceData:=dataTable)
Dim pt As PivotTable
For Each pt in PivotSheet.PivotTables
pt.ChangePivotCache pc 'Invalid Procedure Call Or Argument
Next pt
What am I doing wrong here?
Combine the two approaches:
Dim bCreated As Boolean
Dim lngMasterIndex As Long
Dim pt As PivotTable
For Each pt In PivotSheet.PivotTables
If Not bCreated Then
pt.ChangePivotCache ThisWorkbook.PivotCaches.Create( _
SourceType:=xlDatabase, _
SourceData:=DataTable)
bCreated = True
lngMasterIndex = pt.CacheIndex
Else
pt.CacheIndex = lngMasterIndex
End If
Next pt
If you hate snorkeling the code, to make it work, this is the short and dirty way to do it:
For Each pt in PivotSheet.PivotTables
On Error Resume Next
pt.ChangePivotCache pc 'works for the first entry
pt.CacheIndex = pc.Index 'works for all the others
On Error GoTo 0
Next PT

Excel VBA: Output Distinct Values and Subtotals

I have data of this form:
Category Source Amount
Dues FTW $100
Donations ODP $20
Donations IOI $33
Dues MMK $124
There is no sort order. The categories are unknown at compile time. I want a VBA macro to cycle through the range, output a list of distinct values, with the subtotals for each. For the above data, it would look like this:
Category Total Amount
Dues $224
Donations $55
How can I do this? Also, is there a way to make the macro run every time the table above is updated, or is it necessary for the user to click a button?
You may want to use a built in Excel feature to do this. Looping can take a long time and be problematic if you have a lot of values to loop through.
Something like the following might get you started on creating a pivot table (from http://www.ozgrid.com/News/pivot-tables.htm)
Sub MakeTable()
Dim Pt As PivotTable
Dim strField As String
'Pass heading to a String variable
strField = Selection.Cells(1, 1).Text
'Name the list range
Range(Selection, Selection.End(xlDown)).Name = "Items"
'Create the Pivot Table based off our named list range.
'TableDestination:="" will force it onto a new sheet
ActiveWorkbook.PivotCaches.Add(SourceType:=xlDatabase, _
SourceData:="=Items").CreatePivotTable TableDestination:="", _
TableName:="ItemList"
'Set a Pivot Table variable to our new Pivot Table
Set Pt = ActiveSheet.PivotTables("ItemList")
'Place the Pivot Table to Start from A3 on the new sheet
ActiveSheet.PivotTableWizard TableDestination:=Cells(3, 1)
'Move the list heading to the Row Field
Pt.AddFields RowFields:=strField
'Move the list heading to the Data Field
Pt.PivotFields(strField).Orientation = xlDataField
End Sub
This is for subtotals (though I much prefer pivot tables)
http://msdn.microsoft.com/en-us/library/aa213577(office.11).aspx
EDIT:
I reread and have the following thoughts. Set up the pivot table on a separate sheet (without using any code) then put the following code on the sheet that has the pivot table so that the table will update everytime the sheet is selected.
Private Sub Worksheet_Activate()
Dim pt As PivotTable
'change "MiPivot" to the name of your pivot table
Set pt = ActiveSheet.PivotTables("MyPivot")
pt.RefreshTable
End Sub
Edit #2
Refresh all pivot tables on sheet
http://www.ozgrid.com/VBA/pivot-table-refresh.htm
Private Sub Worksheet_Activate()
Dim pt As PivotTable
For Each pt In ActiveSheet.PivotTables
pt.RefreshTable
Next pt
End Sub
The link has multiple options on how to refresh pivot tables in the sheet/workbook.