93

I have a workbook with 20 different pivot tables. Is there any easy way to find all the pivot tables and refresh them in VBA?

Vincent
  • 417
  • 3
  • 12
Lipis
  • 21,388
  • 20
  • 94
  • 121

10 Answers10

188

Yes.

ThisWorkbook.RefreshAll

Or, if your Excel version is old enough,

Dim Sheet as WorkSheet, Pivot as PivotTable
For Each Sheet in ThisWorkbook.WorkSheets
    For Each Pivot in Sheet.PivotTables
        Pivot.RefreshTable
        Pivot.Update
    Next
Next
airstrike
  • 2,270
  • 1
  • 25
  • 26
GSerg
  • 76,472
  • 17
  • 159
  • 346
  • 3
    Fantastic, I had to use it since I wanted to refresh the pivots AFTER I got new external data, so ThisWorkbook.RefreshAll wasn't working for me. – Yasskier Sep 22 '14 at 21:42
  • 8
    Just a note. The `ThisWorkbook.RefreshAll` method for some reason not works, if `Application.Calculation = xlCalculationManual`. Set the calculation property to `Application.Calculation = xlCalculationAutomatic` before using the code. – kolcinx Jul 10 '16 at 08:30
  • @GSerg Does this work for Pivot Tables that are linked to SAS? Normally I have to click each pivot table and in the SAS ribbon I have to click refresh which will only refresh that one pivot table. – THAT newbie Oct 19 '16 at 23:33
  • 3
    @GSerg Sorry for reviving this old post, but I have a question (posted [Here](http://stackoverflow.com/questions/40360844/pivot-table-refreshtable-vs-update-methods)): Do we need to do an `Update` after the `RefreshTable`? what's the difference between the two? – Oscar Anthony Nov 02 '16 at 12:45
  • I have a simple spreadsheet with a simple pivot table. When I call `ThisWorkbook.RefreshAll` inside of the `Worksheet_Change` event I get a stack overflow. Changing it to `ActiveWorkbook` fixed the issue. –  Sep 18 '18 at 17:04
  • 1
    I'm glad you showed both answers. I prefer the second because I have Query Tables in my scenario that I do not want to refresh. The second option only affects Pivot Tables. – Ben Aug 05 '20 at 01:26
  • RefreshAll refreshes everything, not just the Pivot Tables. This can be VERY problematic is you are using Data Connections that require specific refresh status. – Frank Ball Jun 11 '22 at 16:10
29

This VBA code will refresh all pivot tables/charts in the workbook.

Sub RefreshAllPivotTables()

Dim PT As PivotTable
Dim WS As Worksheet

    For Each WS In ThisWorkbook.Worksheets

        For Each PT In WS.PivotTables
          PT.RefreshTable
        Next PT

    Next WS

End Sub

Another non-programatic option is:

  • Right click on each pivot table
  • Select Table options
  • Tick the 'Refresh on open' option.
  • Click on the OK button

This will refresh the pivot table each time the workbook is opened.

Robert Mearns
  • 11,796
  • 3
  • 38
  • 42
22

ActiveWorkbook.RefreshAll refreshes everything, not only the pivot tables but also the ODBC queries. I have a couple of VBA queries that refer to Data connections and using this option crashes as the command runs the Data connections without the detail supplied from the VBA

I recommend the option if you only want the pivots refreshed

Sub RefreshPivotTables()     
  Dim pivotTable As PivotTable     
  For Each pivotTable In ActiveSheet.PivotTables         
    pivotTable.RefreshTable     
  Next 
End Sub 
jonsca
  • 10,218
  • 26
  • 54
  • 62
Kevin
  • 221
  • 2
  • 2
  • 1
    check the most voted answer.. the second approach is actually what you tried here.. but for the whole boom.. not only for the active sheet.. either case it really depends.. and I haven't touch it since.. – Lipis Sep 25 '12 at 23:46
  • What if the pivot table is not in the active sheet? – Freakishly May 10 '18 at 00:38
8

In certain circumstances you might want to differentiate between a PivotTable and its PivotCache. The Cache has it's own refresh method and its own collections. So we could have refreshed all the PivotCaches instead of the PivotTables.

The difference? When you create a new Pivot Table you are asked if you want it based on a previous table. If you say no, this Pivot Table gets its own cache and doubles the size of the source data. If you say yes, you keep your WorkBook small, but you add to a collection of Pivot Tables that share a single cache. The entire collection gets refreshed when you refresh any single Pivot Table in that collection. You can imagine therefore what the difference might be between refreshing every cache in the WorkBook, compared to refreshing every Pivot Table in the WorkBook.

5

There is a refresh all option in the Pivot Table tool bar. That is enough. Dont have to do anything else.

Press ctrl+alt+F5

  • 3
    I disagree. What if Lipis wants to automate the refresh process for example, whenever a cell is changed? – StockB Oct 09 '13 at 11:44
1

You have a PivotTables collection on a the VB Worksheet object. So, a quick loop like this will work:

Sub RefreshPivotTables()
    Dim pivotTable As PivotTable
    For Each pivotTable In ActiveSheet.PivotTables
        pivotTable.RefreshTable
    Next
End Sub

Notes from the trenches:

  1. Remember to unprotect any protected sheets before updating the PivotTable.
  2. Save often.
  3. I'll think of more and update in due course... :)

Good luck!

LohanJ
  • 45
  • 1
0

The code

Private Sub Worksheet_Activate()
    Dim PvtTbl As PivotTable
        Cells.EntireColumn.AutoFit
        For Each PvtTbl In Worksheets("Sales Details").PivotTables
        PvtTbl.RefreshTable
        Next
End Sub 

works fine.

The code is used in the activate sheet module, thus it displays a flicker/glitch when the sheet is activated.

HaveNoDisplayName
  • 8,291
  • 106
  • 37
  • 47
0

Even we can refresh particular connection and in turn it will refresh all the pivots linked to it.

For this code I have created slicer from table present in Excel:

Sub UpdateConnection()
        Dim ServerName As String
        Dim ServerNameRaw As String
        Dim CubeName As String
        Dim CubeNameRaw As String
        Dim ConnectionString As String

        ServerNameRaw = ActiveWorkbook.SlicerCaches("Slicer_ServerName").VisibleSlicerItemsList(1)
        ServerName = Replace(Split(ServerNameRaw, "[")(3), "]", "")

        CubeNameRaw = ActiveWorkbook.SlicerCaches("Slicer_CubeName").VisibleSlicerItemsList(1)
        CubeName = Replace(Split(CubeNameRaw, "[")(3), "]", "")

        If CubeName = "All" Or ServerName = "All" Then
            MsgBox "Please Select One Cube and Server Name", vbOKOnly, "Slicer Info"
        Else
            ConnectionString = GetConnectionString(ServerName, CubeName)
            UpdateAllQueryTableConnections ConnectionString, CubeName
        End If
    End Sub

    Function GetConnectionString(ServerName As String, CubeName As String)
        Dim result As String
        result = "OLEDB;Provider=MSOLAP.5;Integrated Security=SSPI;Persist Security Info=True;Initial Catalog=" & CubeName & ";Data Source=" & ServerName & ";MDX Compatibility=1;Safety Options=2;MDX Missing Member Mode=Error;Update Isolation Level=2"
        '"OLEDB;Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=True;Initial Catalog=" & CubeName & ";Data Source=" & ServerName & ";Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;Use Encryption for Data=False;Tag with column collation when possible=False"
        GetConnectionString = result
    End Function

    Function GetConnectionString(ServerName As String, CubeName As String)
    Dim result As String
    result = "OLEDB;Provider=MSOLAP.5;Integrated Security=SSPI;Persist Security Info=True;Initial Catalog=" & CubeName & ";Data Source=" & ServerName & ";MDX Compatibility=1;Safety Options=2;MDX Missing Member Mode=Error;Update Isolation Level=2"
    GetConnectionString = result
End Function

Sub UpdateAllQueryTableConnections(ConnectionString As String, CubeName As String)
    Dim cn As WorkbookConnection
    Dim oledbCn As OLEDBConnection
    Dim Count As Integer, i As Integer
    Dim DBName As String
    DBName = "Initial Catalog=" + CubeName

    Count = 0
    For Each cn In ThisWorkbook.Connections
        If cn.Name = "ThisWorkbookDataModel" Then
            Exit For
        End If

        oTmp = Split(cn.OLEDBConnection.Connection, ";")
        For i = 0 To UBound(oTmp) - 1
            If InStr(1, oTmp(i), DBName, vbTextCompare) = 1 Then
                Set oledbCn = cn.OLEDBConnection
                oledbCn.SavePassword = True
                oledbCn.Connection = ConnectionString
                oledbCn.Refresh
                Count = Count + 1
            End If
        Next
    Next

    If Count = 0 Then
         MsgBox "Nothing to update", vbOKOnly, "Update Connection"
    ElseIf Count > 0 Then
        MsgBox "Update & Refresh Connection Successfully", vbOKOnly, "Update Connection"
    End If
End Sub
Rajiv Singh
  • 958
  • 1
  • 9
  • 14
-2

I have use the command listed below in the recent past and it seems to work fine.

ActiveWorkbook.RefreshAll

Hope that helps.

  • 7
    It helps a lot.. but didn't you see that it's actually written above? Like 4 years ago?! (http://stackoverflow.com/a/70976/8418) – Lipis Sep 18 '12 at 15:46
-3

If you are using MS Excel 2003 then go to view->Tool bar->Pivot Table From this tool bar we can do refresh by clicking ! this symbol.

Karuna
  • 1