'VBA - Macro Copied Workbook, Pivot Data Source not Updating, Error with Pivot Cache?

I'm writing a macro that takes a master file, takes a list of sales people, and for each sales person (RSL) creates individual copies of the master file and edits them so that they only see their own data. I've gotten everything to work but the only thing I haven't figured out is how to update the Pivot table data sources. When I make a copy of the workbook, the pivot data source stays linked to the original master instead of updating to the new workbook (which I am then editing). Is there any way to get around this? I've looked and a few different people are suggesting its an issue with pivot caches but I've had no luck with any fixes.

This is what the new workbook's pivot table data source points too, it points to the old master file rather than just the Sales table.

I'm still pretty new to VBA so any help is greatly appreciated. Feels so close to working properly.

As a quick run-through of the macro it should, for each sales person in list on "graphs" tab > copy master > Delete sales region trending tab > delete everyone but that sales person from sales data > delete everyone but that sales person in hardware data > refresh all pivot tables > save as a copy in a desktop field tracings folder > close.

Side question: Does it matter where you define a DIM, in/outside a loop if its being changed each loop?

Edit: Here is my final working macro

     Sub updatepivot(wb As Workbook)
    
        Dim pt As PivotTable, ws As Worksheet, ar
        For Each ws In wb.Sheets
            For Each pt In ws.PivotTables
                ar = Split(pt.PivotCache.SourceData, "!")
                If UBound(ar) = 1 Then
                   'Debug.Print pt.Name, pt.PivotCache.SourceData, ar(1)
                   pt.ChangePivotCache wb.PivotCaches.Create(SourceType:=xlDatabase, SourceData:=ar(1))
                   pt.SaveData = True
                End If
            Next
        Next
    
    End Sub

Sub CreateTracingsStack()

    Dim wsGraphs As Worksheet: Set wsGraphs = Sheets("Graphs")
    Dim new_wb As Workbook, ws As Worksheet
    Dim UserName As String, myFolder As String, rslname As String, TimeTaken As String, myDate As String
    Dim LastRow As Long, i As Long, n As Long
    Dim StartTime As Double
    
    ' Message box
    myDate = InputBox("Please Enter Tracings Date: ex. June 2021")
        If (StrPtr(myDate) = 0) Then
            Exit Sub
        End If
    'Debug.Print myDate
 
    ' Start timer
    StartTime = Timer
 
    ' Determine range addresses
    Dim addrSales As String, rngSales As Range
    With Sheets("Sales Data-No Hardware")
        LastRow = .Cells(Rows.Count, 2).End(xlUp).Row
        addrSales = .Range("B2:S" & LastRow).Address
    End With
    'Debug.Print "SalesData LastRow", LastRow, addrSales
 
    Dim addrHardware As String, rngHardware As Range
    With Sheets("Hardware Data")
        LastRow = Sheets("Hardware Data").Cells(Rows.Count, 2).End(xlUp).Row
        addrHardware = Sheets("Hardware Data").Range("A1:Q" & LastRow).Address
    End With
    'Debug.Print "HarwareData LastRow", LastRow, addrHardware

    ' scan each RSL
    Application.ScreenUpdating = False
    LastRow = wsGraphs.Range("BA" & wsGraphs.Rows.Count).End(xlUp).Row
    For i = 1 To LastRow
        rslname = wsGraphs.Range("BA" & i)
        
        ' Copy workbook
        ActiveWorkbook.Sheets.Copy
        Set new_wb = ActiveWorkbook
        
        ' Delete Sales Region Trending Tab
        Application.DisplayAlerts = False
        For Each ws In new_wb.Worksheets
            If ws.Name = "Sales Region Trending" Then
                ws.Delete
            End If
        Next
        Application.DisplayAlerts = False

         ' Filter and delete from sales data
        Dim SalesRange As Range
        Set SalesRange = new_wb.Sheets("Sales Data-No Hardware").Range("B2:S" & [SalesData].Cells([SalesData].Rows.Count, 2).End(xlUp).Row)
        SalesRange.AutoFilter Field:=14, Criteria1:="<>" & rslname
    
        On Error Resume Next
        With SalesRange
            .Offset(1).Resize(.Rows.Count - 1).SpecialCells(xlCellTypeVisible).Delete
        End With
        Err.Clear
        On Error GoTo 0
        
        'Filter and delete hardware data
        Set ws = new_wb.Sheets("Hardware Data")
        Set rngHardware = ws.Range(addrHardware)
        rngHardware.AutoFilter Field:=14, Criteria1:="<>" & rslname
        
        On Error Resume Next
        With rngHardware
            .Offset(1).Resize(.Rows.Count - 0).SpecialCells(xlCellTypeVisible).Delete
        End With
        Err.Clear
        On Error GoTo 0
        ws.AutoFilterMode = False
        
        ' change data source
        Call updatepivot(new_wb)

        'Refresh all pivot tables
        Calculate
        ActiveWorkbook.RefreshAll
        
        'Saving tracing copy
        UserName = Environ("Username")
        myFolder = "C:\Users\" & UserName & "\Desktop\Field Tracings\"
        
        'Creates Field Tracings folder if missing
        If Dir(myFolder, vbDirectory) = "" Then
            MkDir myFolder
        End If
            
        'Saves Active workbook
        rslsavename = rslname & " - " & myDate & " Tracings"
        new_wb.SaveAs Filename:=myFolder & rslsavename, FileFormat:=xlOpenXMLWorkbookMacroEnabled
        
        'Close activeworkbook
        new_wb.Close False
        n = n + 1
    Next i
    
    Application.ScreenUpdating = True
    
    TimeTaken = Format((Timer - StartTime) / 86400, "hh:mm:ss")
    MsgBox n & " workbooks created in " & myFolder & vbNewLine & "Time Taken: " & TimeTaken & " (hours, minutes, seconds)", vbInformation
    
End Sub


Solution 1:[1]

If you have named ranges try removing the external reference part of the source data.

Update - using ChangePivotCache

Sub updatepivot(wb As Workbook)

    Dim pt As PivotTable, ws As Worksheet, ar
    For Each ws In wb.Sheets
        For Each pt In ws.PivotTables
            ar = Split(pt.PivotCache.SourceData, "!")
            If UBound(ar) = 1 Then
               Debug.Print pt.Name, pt.PivotCache.SourceData, ar(1)
               pt.ChangePivotCache wb.PivotCaches.Create(SourceType:=xlDatabase, SourceData:=ar(1))
            End If
        Next
    Next

End Sub

Sub CreateTracings()

    Dim wsGraphs As Worksheet: Set wsGraphs = Sheets("Graphs")
    
    Dim new_wb As Workbook, ws As Worksheet
    Dim UserName As String, myFolder As String, rslname As String
    Dim LastRow As Long, i As Long, n As Long
 
    ' determine range addresses
    Dim addrSales As String, rngSales As Range
    With Sheets("Sales Data-No Hardware")
        LastRow = .Cells(Rows.Count, 2).End(xlUp).Row
        addrSales = .Range("B2:S" & LastRow).Address
    End With
    'Debug.Print "SalesData LastRow", LastRow, addrSales
 
    Dim addrHardware As String, rngHardware As Range
    With Sheets("Hardware Data")
        LastRow = Sheets("Hardware Data").Cells(Rows.Count, 2).End(xlUp).Row
        addrHardware = Sheets("Hardware Data").Range("A1:Q" & LastRow).Address
    End With
    'Debug.Print "HarwareData LastRow", LastRow, addrHardware

    ' scan each RSL
    Application.ScreenUpdating = False
    LastRow = wsGraphs.Range("BA" & wsGraphs.Rows.Count).End(xlUp).Row
    For i = 1 To LastRow
        rslname = wsGraphs.Range("BA" & i)
        
        'Copy workbook
        ActiveWorkbook.Sheets.Copy
        Set new_wb = ActiveWorkbook
        
        'Delete Sales Region Trending Tab
        Application.DisplayAlerts = False
        For Each ws In new_wb.Worksheets
            If ws.Name = "Sales Region Trending" Then
                ws.Delete
            End If
        Next
        Application.DisplayAlerts = True
       
        'Filter and delete in Sales Data
        Set ws = new_wb.Sheets("Sales Data-No Hardware")
        Set rngSales = ws.Range(addrSales)
        rngSales.AutoFilter Field:=14, Criteria1:="<>" & rslname
        
        On Error Resume Next
        With rngSales
            .Offset(1).Resize(.Rows.Count - 1).SpecialCells(xlCellTypeVisible).EntireRow.Delete
        End With
        Err.Clear
        On Error GoTo 0
        ws.AutoFilterMode = False
        
        'Filter and delete hardware data
        Set ws = new_wb.Sheets("Hardware Data")
        Set rngHardware = ws.Range(addrHardware)
        rngHardware.AutoFilter Field:=14, Criteria1:="<>" & rslname
        
        On Error Resume Next
        With rngHardware
            .Offset(1).Resize(.Rows.Count - 0).SpecialCells(xlCellTypeVisible).EntireRow.Delete
        End With
        Err.Clear
        On Error GoTo 0
        ws.AutoFilterMode = False
        
        ' change data source
        Call updatepivot(new_wb)

        'Refresh all pivot tables
        Calculate
        new_wb.RefreshAll
        
        'Saving tracing copy
        UserName = Environ("Username")
        myFolder = "C:\Users\" & UserName & "\Desktop\Field Tracings\"
        
        'Creates Field Tracings folder if missing
        If Dir(myFolder, vbDirectory) = "" Then
            MkDir myFolder
        End If
            
        'Saves Active workbook
        new_wb.SaveAs Filename:=myFolder & rslname, FileFormat:=xlOpenXMLWorkbookMacroEnabled
        
        'Close activeworkbook
        new_wb.Close False
        n = n + 1
    Next i
    Application.ScreenUpdating = True
    MsgBox n & " workbooks created in " & myFolder, vbInformation
    
End Sub

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1