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
Related
I have a PivotTable that automatically refreshes every time I refresh a data set to our mySQL database in our office.
My Excel file launches a query against the mySQL database and returns a data table, and I have two PivotTables on separate sheets that will automatically update every time that is done. My code for that is below:
Sub UpdatePivots()
' This sub is intended to update all pivot charts in the by switching to the appropriate
' worksheet, locating the appropriate pivot table, and updating them.
Dim ws As Worksheet
Dim PT As PivotTable
For Each ws In ActiveWorkbook.Worksheets '<~~ Loop all worksheets in workbook
For Each PT In ws.PivotTables '<~~ Loop all pivot tables in worksheet
PT.PivotCache.Refresh
Next PT
Next ws
End Sub
What I am looking to do calculate a YIELD for some of the fields in the Pivot Table. The table currently looks like this below:
As you can see, I added in the "YIELD" column automatically and simply did an:
=GETPIVOTDATA("Pass / Fail",$B$5,"Job ID","Job 1","Pass / Fail","Pass")/GETPIVOTDATA("Pass / Fail",$B$5,"Job ID","Job 1")
Ideally, what I would like to do is add to my UpdatePivots() macro to automatically calculate the yield (Pass / Grand Total) for each of the rows listed.
This table is subject to change in size - sometimes I am looking at only 3 jobs in a given month (like September so far), other times my boss wants me to run this report for an entire year where I can have an upwards of 100 jobs. So I would like to use some pseudo code that might look like this:
Cell F6.Text = YIELD
<Apply Pivot Table Formatting to Cell F6>
for each row in pivottable {
Cell Fx.Value = Pass / Grand Total
}
Can anybody help me do that? I have tried brainstorming on paper, but don't even know where to start.
PS - How can I get the Pivot Table to stop that terrible formatting, and to keep my grayed cells? I want to eventually add in charts.
Thank you!!
The following code satisfies my need:
Sub CalculateYield()
k = Cells(Rows.Count, 2).End(xlUp).Row
For r = 9 To k
Cells(r, 6).Formula = "=" & Cells(r, 3).Address(False, False) & "/" & Cells(r, 5).Address(False, False)
Next
End Sub
After filtering on a column I end up with 4 rows instead of 105 but my code is still seeing 105 rows, how can i automatically refresh my pivot table as i appy a filter.I'll filter my sheet many times so i want my pivot table to adapt to my filtering (don't want to apply the filter directly on the pivot table but to automatize the procedure)
LastRow = alarmes.Cells(Rows.Count, 1).End(xlUp).Row
LastCol = 11
Set PRange = alarmes.Cells(1, 1).Resize(LastRow, LastCol)
Set PCache = Application.ThisWorkbook.PivotCaches.Create _
(SourceType:=xlDatabase, SourceData:=PRange)
Set PTable = PCache.CreatePivotTable _
(TableDestination:=graphe_dos.Cells(1, 1), TableName:="Test")
You can't create a PivotTable from a non-contiguous range. And filtering a PivotTable's source data has no effect on a PivotTable. So you either need to delete the hidden rows in the source Table, and then use the entire remaining Table block, or filter the PivotItems in the PivotTable itself.
If you want to filter a PivotField to match the items in the Table, then you need to iterate through the PivotItems (or SlicerItems if there is a Slicer connected to the PivotField) and set the .Visible (or .Selected for SlicerItems) property to TRUE for the things you want to keep, and FALSE for other items.
There are many potential bottlenecks when doing this, and if you don't code around them, then it might take minutes to iterate through a PivotField with as little as 20,000 PivotItems in it. See my post at http://dailydoseofexcel.com/archives/2013/11/14/filtering-pivots-based-on-external-ranges/ for more on what to watch out for, and then see my answers at the following links that program around these bottlenecks:
Filtering on SlicerItems
Filtering on PivotItems
Perhaps an easy workaround is to set up a PivotTable Slicer, and use the value that the user selects in that PivotTable Slicer to filter the Table on the same value. See How to link a Table and a Pivot Table using Slicers in Excel?
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!
I found this code on Spreadsheetguru and I have an issue with editing the code.
Sub CreatePivotTable()
'PURPOSE: Creates a brand new Pivot table on a new worksheet from data in the ActiveSheet
'Source: www.TheSpreadsheetGuru.com
Dim sht As Worksheet
Dim pvtCache As PivotCache
Dim pvt As PivotTable
Dim StartPvt As String
Dim SrcData As String
'Determine the data range you want to pivot
SrcData = ActiveSheet.Name & "!" & Range("A1:R100").Address(ReferenceStyle:=xlR1C1)
'Create a new worksheet
Set sht = Sheets.Add
'Where do you want Pivot Table to start?
StartPvt = sht.Name & "!" & sht.Range("A3").Address(ReferenceStyle:=xlR1C1)
'Create Pivot Cache from Source Data
Set pvtCache = ActiveWorkbook.PivotCaches.Create( _
SourceType:=xlDatabase, _
SourceData:=SrcData)
'Create Pivot table from Pivot Cache
Set pvt = pvtCache.CreatePivotTable( _
TableDestination:=StartPvt, _
TableName:="PivotTable1")
End Sub
Why is it not possible for me to Define SrcData as Worksheets("SHEETNAME").Range("A1:A100")? It returns a type 13 error: mismatch. I tried finding answers online and most examples referred the SrcData for ActiveSheet.Range instead of a defined sheet.
Thank you!
It would also greatly help if you could show me how an example pivot would work for the Sheet("PivotExp") on this sheet.http://imgur.com/TShQ1ls
Thank you so much!
Why is it not possible for me to Define SrcData as
Worksheets("SHEETNAME").Range("A1:A100")?
Pivot table works on 2 dimensional data (tabular form), i.e rows and columns, but with A1:A100 your are supplying only 1 dimensional data (list form). Also you need to assign source data as per syntax rules.
It returns a type 13 error: mismatch.
Mismatch error due to above reason.
It would also greatly help if you could show me how an example pivot
would work for the Sheet("PivotExp") on this
sheet.http://imgur.com/TShQ1ls
Due to some reason, image was not visible, but instead you can visit following example link : http://analysistabs.com/excel-vba/pivot-tables-examples/ which show how to create Pivot Tables with VBA code.
Since, your given code is missing lot of Pivot related information, a Pivot wont' get formed but by visiting above link you can have idea, what things are missing in it.
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.