Loop through Worksheets to create Pivot Table from existing tables - excel

I've searched and found Create Pivot tables within a for loop, but haven't been able to get it to work.
I've got a workbook with 11 sheets and a table in each sheet, so I'd like to create a loop that will go through every sheet and create a pivot table next to the existing table.
I'm getting an "Invalid Procedure or argument " error for the Pivot Table code.
This code is probably far too simple, but here's my attempt:
sub PivotLoop()
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
Set cache = Nothing
Set PivT = Nothing
With ws
On Error Resume Next
On Error GoTo 0
Set cache = ThisWorkbook.PivotCaches.Create(SourceType:=xlDatabase, _
SourceData:=Range("Table" & ws.Index), Version:=xlPivotTableVersion15)
Set PivT = ws.PivotTables.Add(PivotCache:=cache, _
TableDestination:=Range("h2"), TableName:="PivotTable" & ws.Index)
End With
Next ws
End Sub

It's done essentially like this. In your specific case, it will obviously be slightly different, depending on your sheet names, your ranges, whether you want counts, sums, averages, etc.
Option Explicit
Sub test()
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
' don't touch a sheet with a specific name...if needed...
If ws.Name <> "Master" Then
' now we want to build a pivot table
Range("A1").Select
Sheets.Add
ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:= _
"Sheet1!R1C1:R10C3", Version:=xlPivotTableVersion15).CreatePivotTable _
TableDestination:="Sheet5!R3C1", TableName:="PivotTable1", DefaultVersion _
:=xlPivotTableVersion15
With ActiveSheet.PivotTables("PivotTable1").PivotFields("field1")
.Orientation = xlRowField
.Position = 1
End With
With ActiveSheet.PivotTables("PivotTable1").PivotFields("field2")
.Orientation = xlColumnField
.Position = 1
End With
ActiveSheet.PivotTables("PivotTable1").AddDataField ActiveSheet.PivotTables( _
"PivotTable1").PivotFields("field3"), "Sum of field3", xlSum
End If
Next ws
End Sub
It helps a lot if you turn on the Macro recorder and see what kind of code it produces and you click through the steps.

Got it to work if anyone else wants to do it.
sub PivotTableLoop ()
Dim ws as Worksheet
Dim PivC As PivotCache
Dim PivT As PivotTable
Dim Table As ListObject
For Each ws In WeeklyReport.Worksheets
Set PivC = Nothing
Set PivT = Nothing
Set Table = Nothing
On Error Resume Next
' Set PivotTable Cache
Set PivC = WeeklyReport.PivotCaches.Create(SourceType:=xlDatabase, _
SourceData:=ws.ListObjects(1), Version:=xlPivotTableVersion15)
' Create the PivotTable
Set PivT = ws.PivotTables.Add(PivotCache:=PivC, _
TableDestination:=ws.Range("i2"), TableName:="PivotTable" & ws.Index)
On Error GoTo 0
For Each PivT In ws.PivotTables
PivT.PivotFields("day").Orientation = xlRowField
PivT.PivotFields("Competitor").Orientation = xlColumnField
PivT.AddDataField PivT.PivotFields("Sales"), xlSum
PivT.PivotFields("Sales").NumberFormat = "$0.00"
Next PivT
Next ws
End Sub

Related

Can not create pivot table by VBA but I can manually create pivot table from same data source

Sub CreatePivot()
Dim NewSheet As Worksheet
Dim PTCache As PivotCache
Dim PT As PivotTable
Dim PTRange As Range
Dim FinalRow As Long
Dim FinalCol As Long
Set NewSheet = Workbooks("東京威力_樞紐分
析.xlsm").Sheets.Add(Before:=Workbooks("東京威力_樞紐分
析.xlsm").Worksheets(1))
NewSheet.Name = "Summary"
For Each PT In NewSheet.PivotTables
PT.TableRange2.Clear
Next PT
Set PTRange = getTable("Table1").Range
'Create PivotCaches
Set PTCache = Workbooks("東京威力_樞紐分
析.xlsm").PivotCaches.Create(SourceType:=xlDatabase,
SourceData:=PTRange.Address)
'Create PivotTable
Set PT =
PTCache.CreatePivotTable(TableDestination:=NewSheet.Cells(2,
2),tableName:="PivotTable1")
'ManualUpdate On
PT.ManualUpdate = True
PT.AddFields RowFields:=Array("Recharge BU", "Main Category"),
ColumnFields:="Recharge To"
With PT.PivotFields("Hours")
.Orientation = xlDataField
.Function = xlSum
.Position = 1
.NumberFormat = "#,##0.00"
.Name = "Total - Hours"
End With
'Calcu PivotTable
PT.ManualUpdate = False
PT.ManualUpdate = True
End Sub
-------------------------------------------------------------------------
Function getTable(tableName As String) As ListObject
Dim FinalRow As Long
With Workbooks("東京威力_樞紐分析.xlsm").Worksheets("原始資料")
On Error GoTo ErrorHandler
FinalRow = .Cells(Rows.Count, 1).End(xlUp).row
Set getTable = .ListObjects(tableName)
End With
Exit Function
ErrorHandler:
Debug.Print Err.Number; ":" & Err.Description
If getTable Is Nothing Then
Workbooks("東京威力_樞紐分析.xlsm").Worksheets("原始資料").ListObjects.Add(xlSrcRange,
Workbooks("東京威力_樞紐分析.xlsm").Worksheets("原始資料").Range("A1:AK" & FinalRow), , xlYes).Name = "Table1"
Set getTable = Worksheets("原始資料").ListObjects(tableName)
End If
Resume Next
End Function
Hi Folks, the Purpose of the code is to create pivot table.
But I Got Error Message
『The PivotTable field name is not valid. To create a PivotTable report, you must use data that is organized as a list with labeled columns. If you are changing the name of a PivotTable field, you must type a new name for the field』 when I created Pivot Table. (at the line==> PTCache.CreatePivotTable)
What could possibly go wrong ? Thanks
PS : I can manually create pivot table from same data source.
SourceData:=PTRange.Address will give us the cell address without the sheet name, e.g. $C$7:$G$17. This do not work for PT.
SourceData requires range reference with sheet name, e.g.
Therefore, it should be
SourceData:= PTRange.Parent.Name & "!" & PTRange.Address. But if your sheet name contain spaces, then it should be SourceData:= "'" & PTRange.Parent.Name & "'!" & PTRange.Address.
Since your data is contained in named-range Table1, using the name as the SourceData will be much much easier.

VBA Excel file size containing multiple pivot tables is huge

I am automating the process of creating pivot tables in excel. The problem I have is that the pivot tables I create using my macro is way larger than the ones I create manually. Both of the pivot tables look identical but there is a great difference in file size.
As seen in the image above, the one created by my macro is about 6 times larger! I suspect that it is the way I cache for the data when creating my pivot tables. So, here is the general code I use to create my pivot tables.
Sub pivottable1()
Dim PSheet As Worksheet, DSheet As Worksheet
Dim PCache As PivotCache
Dim PTable As PivotTable
Dim PField As PivotField
Dim PRange As Range
Dim LastRow As Long
Dim LastCol As Long
Dim PvtTable As PivotTable
Dim SheetName As String
Dim PTName As String
SheetName = "MySheetName1"
PTName = "PivotTable1"
On Error Resume Next
Application.DisplayAlerts = False
Worksheets(SheetName).Delete
Sheets.Add After:=ActiveSheet
ActiveSheet.Name = SheetName
Application.DisplayAlerts = True
Set PSheet = Worksheets(SheetName)
Set DSheet = Worksheets(1)
LastRow = DSheet.Cells(Rows.Count, 1).End(xlUp).Row
LastCol = DSheet.Cells(1, Columns.Count).End(xlToLeft).Column
Set PRange = DSheet.Cells(1, 1).Resize(LastRow, LastCol)
Set PCache = ActiveWorkbook.PivotCaches.Create _
(SourceType:=xlDatabase, SourceData:=PRange). _
CreatePivotTable(TableDestination:=PSheet.Cells(4, 1), _
TABLENAME:=PTName)
Set PTable = PCache.CreatePivotTable _
(TableDestination:=PSheet.Cells(1, 1), TABLENAME:=PTName)
Sheets(SheetName).Select
Set PvtTable = ActiveSheet.PivotTables(PTName)
'Rows
With PvtTable.PivotFields("TypeCol")
.Orientation = xlRowField
.Position = 1
End With
With PvtTable.PivotFields("NameCol")
.Orientation = xlRowField
.Position = 2
End With
'Columns
With PvtTable.PivotFields("CategoryCol")
.Orientation = xlColumnField
.Position = 1
End With
'Values
PvtTable.AddDataField PvtTable.PivotFields("Values1"), "Value Balance", xlSum
PvtTable.AddDataField PvtTable.PivotFields("Values2"), "Value 2 Count", xlCount
With PvtTable
.PivotFields("TypeCol").ShowDetail = False
.TableRange1.Font.Size = 10
.ColumnRange.HorizontalAlignment = xlCenter
.ColumnRange.VerticalAlignment = xlTop
.ColumnRange.WrapText = True
.ColumnRange.Columns.AutoFit
.ColumnRange.EntireRow.AutoFit
.RowAxisLayout xlTabularRow
.ShowTableStyleRowStripes = True
.PivotFields("TypeCol").AutoSort xlDescending, "Value Balance" 'Sort descdending order
.PivotFields("NameCol").AutoSort xlDescending, "Value Balance"
End With
'Change Data field (Values) number format to have thousand seperator and 0 decimal places.
For Each PField In PvtTable.DataFields
PField.NumberFormat = "#,##0"
Next PField
End Sub
This is how I create 6 different pivot tables which all uses the same source of data which is located in the same workbook and is in the first worksheet of that workbook. So, for example my second pivot table macro code would look something like this.
Sub pivottable2()
Dim PSheet As Worksheet, DSheet As Worksheet
Dim PCache As PivotCache
Dim PTable As PivotTable
Dim PField As PivotField
Dim PRange As Range
Dim LastRow As Long
Dim LastCol As Long
Dim PvtTable As PivotTable
Dim SheetName As String
Dim PTName As String
SheetName = "MySheetName2"
PTName = "PivotTable2"
On Error Resume Next
Application.DisplayAlerts = False
Worksheets(SheetName).Delete
Sheets.Add After:=ActiveSheet
ActiveSheet.Name = SheetName
Application.DisplayAlerts = True
Set PSheet = Worksheets(SheetName)
Set DSheet = Worksheets(1)
LastRow = DSheet.Cells(Rows.Count, 1).End(xlUp).Row
LastCol = DSheet.Cells(1, Columns.Count).End(xlToLeft).Column
Set PRange = DSheet.Cells(1, 1).Resize(LastRow, LastCol)
Set PCache = ActiveWorkbook.PivotCaches.Create _
(SourceType:=xlDatabase, SourceData:=PRange). _
CreatePivotTable(TableDestination:=PSheet.Cells(4, 1), _
TABLENAME:=PTName)
Set PTable = PCache.CreatePivotTable _
(TableDestination:=PSheet.Cells(1, 1), TABLENAME:=PTName)
Sheets(SheetName).Select
Set PvtTable = ActiveSheet.PivotTables(PTName)
'Rows
With PvtTable.PivotFields("ManagerCol")
.Orientation = xlRowField
.Position = 1
End With
With PvtTable.PivotFields("IDCol")
.Orientation = xlRowField
.Position = 2
End With
'Columns
With PvtTable.PivotFields("CategoryCol")
.Orientation = xlColumnField
.Position = 1
End With
'Values
PvtTable.AddDataField PvtTable.PivotFields("Values1"), "Value Balance", xlSum
End Sub
All that I change would be the macro name, the worksheet name, the pivot table name and the input rows/columns/data values for the pivot table.
What I hope to accomplish is to reduce the file size of my macro created pivot tables, to something similar of the ones I create manually.
If there is anything extra that you guys would like to know, please comment. I will make an edit with the question and add the details respectively.
You can use the same pivotcache for multiple pivottables (assuming they're based on the same source data).
Untested:
'creates and returns a shared pivotcache object
Function GetPivotCache() As PivotCache
Static pc As PivotCache 'static variables retain their value between calls
Dim pRange As Range
If pc Is Nothing Then 'create if not yet created
Set prRange = Worksheets(1).Range("A1").CurrentRegion
Set pc = ActiveWorkbook.PivotCaches.Create _
(SourceType:=xlDatabase, SourceData:=pRange)
End If
Set GetPivotCache = pc
End Function
Sub pivottable1()
'...
'...
Set PSheet = Worksheets(SheetName)
Set PCache = GetPivotCache() '<<< will be created if needed
Set PTable = PCache.CreatePivotTable _
(TableDestination:=PSheet.Cells(1, 1), TableName:=PTName)
'...
'...
End Sub
I've seen this behavior before. By the very nature of creating Pivots, your WB will bloat up, just as you are seeing now. In the past I have used VBA to create the Pivots, exactly like you are doing, and then right at the end, run a small script to do copy all, and paste special values. That will eliminate most, and perhaps all, of the bloat. Also, instead of saving your WB as XLSX, try XLSB, which will be around 4x smaller than XLSX and open/close around 4x faster than XLSX. I'm wondering why you are even using XLSX, because you can't save Macros in that format. Or, maybe you have a template WB that does all the work, and you simply save new reports as XLSX. Anyway, consider using the XLSB format from now on.

Type mismatch error when creating a PivotCache

I am trying to create a Pivot table on a newsheet using dynamic range, but getting an error that says:
Run time error: 13 Type Mismatch
Googled the error and as per my understanding, the code contains data type that is not matched correctly, but I am not able to figure out where is the error:
Using Excel 2016.
Sub EEE()
Dim PrevSheet As Worksheet
Set PrevSheet = ActiveSheet
Sheets.Add.Name = "Pivottable"
PrevSheet.Select
ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, _
SourceData:=ActiveSheet.UsedRange, _
Version:=xlPivotTableVersion15).CreatePivotTable _
TableDestination:="Pivottable!R3C1", _
TableName:="PivotTable1", _
DefaultVersion:=xlPivotTableVersion15
Sheets("Pivottable").Select
Cells(3, 1).Select
With ActiveSheet.PivotTables("PivotTable1").PivotFields("Faculty")
.Orientation = xlRowField
.Position = 1
End With
With ActiveSheet.PivotTables("PivotTable1").PivotFields("NPS")
.Orientation = xlColumnField
.Position = 1
End With
End Sub
Modified Code - Working
Sub EEE()
Dim rng As Range
Dim pc As PivotCache
Dim pt As PivotTable
Dim ws As Worksheet
Set rng = ActiveSheet.Range("A1").CurrentRegion
Set pc = ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabaseSourceData:=rng.Address)
Set ws = ActiveWorkbook.Worksheets.Add
ws.Name = "NewSheet"
Set pt = pc.CreatePivotTable(TableDestination:=Range("A3"),TableName:="pvttbl")
With pt
.PivotFields("Faculty").Orientation = xlRowField
ActiveSheet.PivotTables("pvttbl").AddDataField ActiveSheet.PivotTable "pvttbl").PivotFields("NPS"), "Count of NPS", xlCount
.PivotFields("NPS").Orientation = xlColumnField
End With
End Sub
You don't say what line is giving the error. But there's a couple of possible culprits.
The line SourceData:=ActiveSheet.UsedRange says "Hey, go make the PivotTable out of everything you find on the active sheet". Not a good idea. Use the exact range where the data is. Either select a cell where there block of data is and use the CurrentRegion e.g.
SourceData:= Activesheet.Range("A1").CurrentRegion
...or even better, turn that SourceData into an Excel Table aka ListObject earlier in the code, and reference that ListObject:
SourceData:= "Table1"
Your code will also fail if you try to run it more than once and you haven't deleted the sheet called "PivotTable" that it created last time.
Here's how I would code this up:
Option Explicit
Sub EEE()
Dim rng As Range
Dim pc As PivotCache
Dim pt As PivotTable
Dim pf As PivotField
Dim ws As Worksheet
Set rng = Range("A1").CurrentRegion '<- Change to the address of the top left cell in your data.
Set pc = ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:=rng.Address)
Set ws = ActiveWorkbook.Worksheets.Add
Set pt = pc.CreatePivotTable(TableDestination:=Range("A1"))
With pt
.PivotFields("Faculty").Orientation = xlRowField
.PivotFields("NPS").Orientation = xlColumnField
End With
End Sub

Multiple Function Call - Public Sub

I am trying to get my Public Sub to make a call against two functions, each creating different pivot tables off of the same data sheet. I know that both of my functions work independently, but I keep getting an "application defined or object defined error" when I combine them in to a single sub.
The macro below does execute the first function and creates the intended pivot table. It just stops when it gets to the second function and provides me with the application or object defined error mentioned above. I have independently defined each function so I am not sure why I am getting an issue.
Option Explicit
Public Sub RunPivots()
Call BuildPivot1("Travel Payment Data by Employee")
Call BuildPivot2("Travel Payment Data by Acct Dim")
End Sub
Function BuildPivot1(paramSheet As String)
On Error GoTo ErrHandle
Dim FinalRow As Long
Dim DataSheet As String
Dim PvtCache As PivotCache
Dim PvtTbl As PivotTable
Dim PvtFld As PivotField
Dim DataRng As Range
Dim TableDest As Range
Dim ws As Worksheet
For Each ws In ThisWorkbook.Sheets
If ws.Name Like "*SQL" & "*" Then
'~~> This check is required to ensure that you don't get an error
'~~> if there is only one sheet left and it matches the delete criteria
If ThisWorkbook.Sheets.Count = 1 Then
MsgBox "There is only one sheet left and you cannot delete it"
Else
'~~> This is required to supress the dialog box which excel shows
'~~> When you delete a sheet. Remove it if you want to see the
'~~~> Dialog Box
Application.DisplayAlerts = False
ws.Delete
Application.DisplayAlerts = True
End If
End If
Next
FinalRow = Cells(Rows.Count, 1).End(xlUp).Row
DataSheet = "Export Worksheet"
' set data range for Pivot Table
Set DataRng = Sheets(DataSheet).Range(Cells(1, 1), Cells(FinalRow, 15))
' check if worksheet exists
Dim currws As Worksheet
For Each currws In ActiveWorkbook.Worksheets
If currws.Name = paramSheet Then
Set ws = Worksheets(paramSheet)
Exit For
End If
Next currws
' create new worksheet if does not exist
If ws Is Nothing Then
Set ws = Worksheets.Add
ws.Name = paramSheet
End If
' set range for Pivot table placement
Set TableDest = Sheets(paramSheet).Cells(1, 1)
' create pivot cache
Set PvtCache = ActiveWorkbook.PivotCaches.Create( _
SourceType:=xlDatabase, _
SourceData:=DataRng, _
Version:=xlPivotTableVersion15)
'check if "PivotTable4" Pivot Table exists
Dim currpvt As PivotTable
For Each currpvt In ws.PivotTables
If currpvt.Name = "PivotTable4" Then
Set PvtTbl = ws.PivotTables("PivotTable4")
Exit For
End If
Next currpvt
' create new pivot table if does not exist
If PvtTbl Is Nothing Then
Set PvtTbl = PvtCache.CreatePivotTable( _
TableDestination:=TableDest, _
TableName:="PivotTable4")
End If
With PvtTbl.PivotFields("Security Org")
.Orientation = xlRowField
.Position = 1
End With
With PvtTbl.PivotFields("Fiscal Month")
.Orientation = xlRowField
.Position = 2
End With
With PvtTbl.PivotFields("Budget Org")
.Orientation = xlRowField
.Position = 3
End With
With PvtTbl.PivotFields("Vendor Name")
.Orientation = xlRowField
.Position = 4
End With
With PvtTbl.PivotFields("Fiscal Year")
.Orientation = xlRowField
.Position = 5
End With
With PvtTbl.PivotFields("Fiscal Year")
.Orientation = xlColumnField
.Position = 1
End With
Range("B:E").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.NumberFormat = "$#,##0.00"
Range("B1").Select
PvtTbl.CompactLayoutColumnHeader = _
"Fiscal Year"
Range("A2").Select
PvtTbl.CompactLayoutRowHeader = _
"Security Org and Vendor"
Range("G8").Select
' Add data field if does not exist
On Error Resume Next
PvtTbl.AddDataField PvtTbl.PivotFields("Dollar Amount"), "Sum of Dollar Amount", xlSum
PvtTbl.PivotFields("Budget Org").ShowDetail = _
False
Exit Function
ErrHandle:
MsgBox Err.Number & " - " & Err.Description, vbCritical, "RUNTIME ERROR"
Exit Function
End Function
Function BuildPivot2(paramSheet As String)
On Error GoTo ErrHandle
Dim FinalRow As Long
Dim DataSheet As String
Dim PvtCache As PivotCache
Dim PvtTbl As PivotTable
Dim PvtFld As PivotField
Dim DataRng As Range
Dim TableDest As Range
Dim ws As Worksheet
For Each ws In ThisWorkbook.Sheets
If ws.Name Like "*SQL" & "*" Then
'~~> This check is required to ensure that you don't get an error
'~~> if there is only one sheet left and it matches the delete criteria
If ThisWorkbook.Sheets.Count = 1 Then
MsgBox "There is only one sheet left and you cannot delete it"
Else
'~~> This is required to supress the dialog box which excel shows
'~~> When you delete a sheet. Remove it if you want to see the
'~~~> Dialog Box
Application.DisplayAlerts = False
ws.Delete
Application.DisplayAlerts = True
End If
End If
Next
FinalRow = Cells(Rows.Count, 1).End(xlUp).Row
DataSheet = "Export Worksheet"
' set data range for Pivot Table
DataSheet = "Export Worksheet"
' set data range for Pivot Table
With Sheets(DataSheet)
Set DataRng = .Range(Cells(1, 1), .Cells(FinalRow, 15))
End With
' check if worksheet exists
Dim currws As Worksheet
For Each currws In ActiveWorkbook.Worksheets
If currws.Name = paramSheet Then
Set ws = Worksheets(paramSheet)
Exit For
End If
Next currws
' create new worksheet if does not exist
If ws Is Nothing Then
Set ws = Worksheets.Add
ws.Name = paramSheet
End If
' set range for Pivot table placement
Set TableDest = Sheets(paramSheet).Cells(1, 1)
' create pivot cache
Set PvtCache = ActiveWorkbook.PivotCaches.Create( _
SourceType:=xlDatabase, _
SourceData:=DataRng, _
Version:=xlPivotTableVersion15)
'check if "PivotTable4" Pivot Table exists
Dim currpvt As PivotTable
For Each currpvt In ws.PivotTables
If currpvt.Name = "PivotTable4" Then
Set PvtTbl = ws.PivotTables("PivotTable4")
Exit For
End If
Next currpvt
' create new pivot table if does not exist
If PvtTbl Is Nothing Then
Set PvtTbl = PvtCache.CreatePivotTable( _
TableDestination:=TableDest, _
TableName:="PivotTable4")
End If
With PvtTbl.PivotFields("Fiscal Year")
.Orientation = xlColumnField
.Position = 1
End With
With PvtTbl.PivotFields("Fund")
.Orientation = xlRowField
.Position = 1
End With
With PvtTbl.PivotFields("Budget Org")
.Orientation = xlRowField
.Position = 2
End With
With PvtTbl.PivotFields("Cost Org")
.Orientation = xlRowField
.Position = 3
End With
Range("B:E").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.NumberFormat = "$#,##0.00"
Range("B1").Select
PvtTbl.CompactLayoutColumnHeader = _
"Fiscal Year"
Range("A2").Select
PvtTbl.CompactLayoutRowHeader = _
"Security Org and Vendor"
Range("G8").Select
' Add data field if does not exist
On Error Resume Next
PvtTbl.AddDataField PvtTbl.PivotFields("Dollar Amount"), "Sum of Dollar Amount", xlSum
PvtTbl.PivotFields("Budget Org").ShowDetail = _
False
Exit Function
ErrHandle:
MsgBox Err.Number & " - " & Err.Description, vbCritical, "RUNTIME ERROR"
Exit Function
End Function
You need to make sure all of your Cells() and Range() calls are qualified with a worksheet object. For example:
Set DataRng = Sheets(DataSheet).Range(Cells(1, 1), Cells(FinalRow, 15))
will fail if the DataSheet worksheet is not the activesheet.
Fix like this:
With Sheets(DataSheet)
Set DataRng = .Range(.Cells(1, 1), .Cells(FinalRow, 15))
End With

Creating Mutiple Pivot Tables from single data source

I am trying to create a pivot table on a new sheet. Additionally, I would like to create another call to create another different pivot table using the same data from the first data sheet.
having trouble with the macro below. I think it is a small error, but can't figure it out.
Sub Macro2()
Dim FinalRow As Long
Dim DataSheet As String
Dim PvtCache As PivotCache
Dim PvtTbl As PivotTable
Dim DataRng As Range
Dim TableDest As Range
Dim ws As Worksheet
FinalRow = Cells(Rows.Count, 1).End(xlUp).Row
DataSheet = ActiveSheet.Name
'set data range for Pivot Table -- ' conversion of R1C1:R & FinalRow & C15
Set DataRng = Sheets(DataSheet).Range(Cells(1, 1), Cells(FinalRow, 15))
Set ws = Worksheets.Add
ws.Name = "Travel Payment Data by Employee"
'set range for Pivot table placement -- Conversion of R1C1
Set TableDest = Sheets("Travel Payment Data by Employee").Cells(1, 1)
Set PvtCache = ActiveWorkbook.PivotCaches.Create(xlDatabase, DataRng, xlPivotTableVersion15)
'check if "PivotTable4" Pivot Table already created (in past runs of this Macro)
Set PvtTbl = ActiveWorkbook.Sheets("Travel Payment Data by Employee").PivotTables("PivotTable4")
With PvtTbl.PivotFields("Security Org")
.Orientation = xlRowField
.Position = 1
End With
With PvtTbl.PivotFields("Fiscal Month")
.Orientation = xlRowField
.Position = 2
End With
With PvtTbl.PivotFields("Budget Org")
.Orientation = xlRowField
.Position = 3
End With
With PvtTbl.PivotFields("Vendor Name")
.Orientation = xlRowField
.Position = 4
End With
With PvtTbl.PivotFields("Fiscal Year")
.Orientation = xlRowField
.Position = 5
End With
With PvtTbl.PivotFields("Fiscal Year")
.Orientation = xlColumnField
.Position = 1
End With
PvtTbl.AddDataField ActiveSheet.PivotTables( _
"PivotTable2").PivotFields("Dollar Amount"), "Sum of Dollar Amount", xlSum
End Sub
Consider the following adjustment with a subroutine calling a function, passing in new worksheet names for new identical pivot tables. If you do not intend identical pivots, adjust them in code conditionally by sheet name or copies of function. The main changes from your code are as follows:
ACTIVE SHEET: Remove the need to search ActiveSheet.Name as adding more worksheets will alter active sheets. Simply hard-code or pass as parameter the data source.
OBJECT CHECK: You need to check if Worksheet exits and PivotTable exists. For these, you will need to iterate through all current such objects and conditionally set worksheet, pivot table objects (see For...Next loops and If ... Is Nothing checks).
For PivotField, since Dollar Amounts will exist in Pivot Table data source but not necessarily display, iterating through all of them might not work like above. So conditionally add only if does not error out see On Resume Next handle.
VBA
Option Explicit
Public Sub RunPivots()
Call BuildPivot("Travel Payment Data by Employee")
Call BuildPivot("Other Worksheet")
Call BuildPivot("Still More Worksheet")
End Sub
Function BuildPivot(paramSheet As String)
On Error GoTo ErrHandle
Dim FinalRow As Long
Dim DataSheet As String
Dim PvtCache As PivotCache
Dim PvtTbl As PivotTable
Dim PvtFld As PivotField
Dim DataRng As Range
Dim TableDest As Range
Dim ws As Worksheet
FinalRow = Cells(Rows.Count, 1).End(xlUp).Row
DataSheet = "DataSourceWorksheet"
' set data range for Pivot Table
Set DataRng = Sheets(DataSheet).Range(Cells(1, 1), Cells(FinalRow, 15))
' check if worksheet exists
Dim currws As Worksheet
For Each currws In ActiveWorkbook.Worksheets
If currws.Name = paramSheet Then
Set ws = Worksheets(paramSheet)
Exit For
End If
Next currws
' create new worksheet if does not exist
If ws Is Nothing Then
Set ws = Worksheets.Add
ws.Name = paramSheet
End If
' set range for Pivot table placement
Set TableDest = Sheets(paramSheet).Cells(1, 1)
' create pivot cache
Set PvtCache = ActiveWorkbook.PivotCaches.Create( _
SourceType:=xlDatabase, _
SourceData:=DataRng, _
Version:=xlPivotTableVersion15)
'check if "PivotTable4" Pivot Table exists
Dim currpvt As PivotTable
For Each currpvt In ws.PivotTables
If currpvt.Name = "PivotTable4" Then
Set PvtTbl = ws.PivotTables("PivotTable4")
Exit For
End If
Next currpvt
' create new pivot table if does not exist
If PvtTbl Is Nothing Then
Set PvtTbl = PvtCache.CreatePivotTable( _
TableDestination:=TableDest, _
TableName:="PivotTable4")
End If
With PvtTbl.PivotFields("Security Org")
.Orientation = xlRowField
.Position = 1
End With
With PvtTbl.PivotFields("Fiscal Month")
.Orientation = xlRowField
.Position = 2
End With
With PvtTbl.PivotFields("Budget Org")
.Orientation = xlRowField
.Position = 3
End With
With PvtTbl.PivotFields("Vendor Name")
.Orientation = xlRowField
.Position = 4
End With
With PvtTbl.PivotFields("Fiscal Year")
.Orientation = xlRowField
.Position = 5
End With
With PvtTbl.PivotFields("Fiscal Year")
.Orientation = xlColumnField
.Position = 1
End With
' Add data field if does not exist
On Error Resume Next
PvtTbl.AddDataField PvtTbl.PivotFields("Dollar Amount"), "Sum of Dollar Amount", xlSum
Exit Function
ErrHandle:
MsgBox Err.Number & " - " & Err.Description, vbCritical, "RUNTIME ERROR"
Exit Function
End Function

Resources