A Step-by-Step Guide to Create a Pivot Table in Excel using VBA – MACRO CODE

Macro Codes To Create A Pivot Table

Before I hand over this guide to you and you start using VBA to create a pivot table, let me confess something. I learned to use VBA a decade ago.

The first time I wrote a macro code to create a pivot table, it was a failure. Since then, I have learned more from my bad coding than from the codes that work.

Today, I will show you a simple way to automate your pivot tables using a macro code.

Normally, when you insert a pivot table in a worksheet, it happens through a simple process, but that entire process is so quick that you never notice what happened.

In VBA, that entire process is the same, just executed using code. In this guide, I’ll show you each step and explain how to write code for it.

Just look at the example below, where you can run this macro code with a button, and it returns a new pivot table in a new worksheet in a flash.

Without any further ado, let’s get started writing our macro code to create a pivot table.

[FULL CODE] Use VBA to Create a Pivot Table in Excel – Macro to Copy-Paste

Sub InsertPivotTable()
'Macro By ExcelChamps.com

'Declare Variables
    Dim PSheet As Worksheet
    Dim DSheet As Worksheet
    Dim PCache As PivotCache
    Dim PTable As PivotTable
    Dim PRange As Range
    Dim LastRow As Long
    Dim LastCol As Long

'Insert a New Blank Worksheet
    On Error Resume Next
    Application.DisplayAlerts = False
    Worksheets("PivotTable").Delete
    Application.DisplayAlerts = True
    On Error GoTo 0

    Sheets.Add Before:=ActiveSheet
    ActiveSheet.Name = "PivotTable"
    Set PSheet = Worksheets("PivotTable")
    Set DSheet = Worksheets("Sales_Data")
    
'Define Data Range
    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)
    
'Define Pivot Cache
    Set PCache = ActiveWorkbook.PivotCaches.Create( _
        SourceType:=xlDatabase, SourceData:=PRange)

'Insert Pivot Table
    Set PTable = PCache.CreatePivotTable( _
        TableDestination:=PSheet.Cells(2, 2), TableName:="SalesPivotTable")
    
'Insert Row Fields
    With PTable.PivotFields("Region")
        .Orientation = xlRowField
        .Position = 1
    End With
    With PTable.PivotFields("Salesperson")
        .Orientation = xlRowField
        .Position = 2
    End With

'Insert Column Fields
    With PTable.PivotFields("Product")
        .Orientation = xlColumnField
        .Position = 1
    End With

'Insert Data Field
    With PTable.PivotFields("Total Sales")
        .Orientation = xlDataField
        .Function = xlSum
        .NumberFormat = "#,##0"
        .Name = "Revenue"
    End With

'Format Pivot Table
    PTable.ShowTableStyleRowStripes = True
    PTable.TableStyle2 = "PivotStyleMedium9"
    
End Sub

Get the Sample File (EC0010)

The Simple 8 Steps to Write a Macro Code in VBA to Create a Pivot Table in Excel

I have split the entire process into 8 simple steps for your convenience. After following these steps, you will be able to automate all your pivot tables.

1. Declare Variables

2. Insert a New Worksheet

3. Define Data Range

4. Create a Pivot Cache

5. Insert a Blank Pivot Table

6. Insert Row and Column Fields

7. Insert Values

8. Format Pivot Table

Finally, your code is ready to use.

[FULL CODE] VBA Code to Create Multiple Pivot Tables from the Same Data Source.

The code below creates eight pivot tables on a new worksheet from the same data source.

Sub Insert_Multiple_Pivot_Tables()

    'Declare Variables
    Dim PSheet As Worksheet
    Dim DSheet As Worksheet
    Dim PCache As PivotCache
    Dim PTable As PivotTable
    Dim PRange As Range
    Dim LastRow As Long
    Dim LastCol As Long
    Dim pvt As PivotTable

    'Delete and Add Worksheet
    On Error Resume Next
    Application.DisplayAlerts = False
    Worksheets("PivotTable").Delete
    Application.DisplayAlerts = True
    On Error GoTo 0

    Sheets.Add Before:=ActiveSheet
    ActiveSheet.Name = "PivotTable"
    Set PSheet = Worksheets("PivotTable")
    Set DSheet = Worksheets("Sales_Data")

    'Define Data Range
    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)

    'Create Pivot Cache Once
    'Create a Pivot Cache from the source data range only once
    Set PCache = ActiveWorkbook.PivotCaches.Create( _
    SourceType:=xlDatabase, _
    SourceData:=PRange)

    'Pivot 1 – Region-Wise Total Sales
    'Create Pivot Table for Region-Wise Total Sales
    Set PTable = PCache.CreatePivotTable( _
        TableDestination:=PSheet.Range("A1"), _
        TableName:="Pivot1_RegionSales")
    With PTable.PivotFields("Region")
        .Orientation = xlRowField
        .Position = 1
    End With
    With PTable.PivotFields("Total Sales")
        .Orientation = xlDataField
        .Function = xlSum
        .Name = "Pivot1_RegionSales"
    End With

    'Pivot 2 – Product-Wise Total Sales
    'Create Pivot Table for Product-Wise Total Sales
    Set PTable = PCache.CreatePivotTable( _
        TableDestination:=PSheet.Range("A8"), _
        TableName:="Pivot2_ProductSales")
    With PTable.PivotFields("Product")
        .Orientation = xlRowField
        .Position = 1
    End With
    With PTable.PivotFields("Total Sales")
        .Orientation = xlDataField
        .Function = xlSum
        .Name = "Pivot2_ProductSales"
    End With

    'Pivot 3 – Payment Mode Wise Total Sales
    'Create Pivot Table for Payment Mode-Wise Total Sales
    Set PTable = PCache.CreatePivotTable( _
        TableDestination:=PSheet.Range("D1"), _
        TableName:="Pivot3_PaymentSales")
    With PTable.PivotFields("Payment Mode")
        .Orientation = xlRowField
        .Position = 1
    End With
    With PTable.PivotFields("Total Sales")
        .Orientation = xlDataField
        .Function = xlSum
        .Name = "Pivot3_PaymentSales"
    End With

    'Pivot 4 – Delivery Status Wise Units Sold
    'Create Pivot Table for Delivery Status-Wise Units Sold
    Set PTable = PCache.CreatePivotTable( _
        TableDestination:=PSheet.Range("D9"), _
        TableName:="Pivot4_DeliveryUnits")
    With PTable.PivotFields("Delivery Status")
        .Orientation = xlRowField
        .Position = 1
    End With
    With PTable.PivotFields("Units Sold")
        .Orientation = xlDataField
        .Function = xlSum
        .Name = "Pivot4_DeliveryUnits"
    End With

    'Pivot 5 – Customer Type Wise Total Sales
    'Create Pivot Table for Customer Type-Wise Total Sales
    Set PTable = PCache.CreatePivotTable( _
        TableDestination:=PSheet.Range("G1"), _
        TableName:="Pivot5_CustomerSales")
    With PTable.PivotFields("Customer Type")
        .Orientation = xlRowField
        .Position = 1
    End With
    With PTable.PivotFields("Total Sales")
        .Orientation = xlDataField
        .Function = xlSum
        .Name = "Pivot5_CustomerSales"
    End With

    'Pivot 6 – Order Priority Wise Units Sold
    'Create Pivot Table for Order Priority-Wise Units Sold
    Set PTable = PCache.CreatePivotTable( _
        TableDestination:=PSheet.Range("A19"), _
        TableName:="Pivot6_PriorityUnits")
    With PTable.PivotFields("Order Priority")
        .Orientation = xlRowField
        .Position = 1
    End With
    With PTable.PivotFields("Units Sold")
        .Orientation = xlDataField
        .Function = xlSum
        .Name = "Pivot6_PriorityUnits"
    End With

    'Pivot 7 – Warranty Wise Units Sold
    'Create Pivot Table for Warranty-Wise Units Sold
    Set PTable = PCache.CreatePivotTable( _
        TableDestination:=PSheet.Range("D16"), _
        TableName:="Pivot7_WarrantyUnits")
    With PTable.PivotFields("Warranty")
        .Orientation = xlRowField
        .Position = 1
    End With
    With PTable.PivotFields("Units Sold")
        .Orientation = xlDataField
        .Function = xlSum
        .Name = "Pivot7_WarrantyUnits"
    End With

    'Pivot 8 – Return Eligibility Wise Units Sold
    'Create Pivot Table for Return Eligibility-Wise Units Sold
    Set PTable = PCache.CreatePivotTable( _
        TableDestination:=PSheet.Range("G8"), _
        TableName:="Pivot8_ReturnUnits")
    With PTable.PivotFields("Return Eligibility")
        .Orientation = xlRowField
        .Position = 1
    End With
    With PTable.PivotFields("Units Sold")
        .Orientation = xlDataField
        .Function = xlSum
        .Name = "Pivot8_ReturnUnits"
    End With

    'Loop through each Pivot Table on the PivotTable worksheet to apply formatting
    For Each pvt In PSheet.PivotTables
        pvt.ShowTableStyleRowStripes = True
        pvt.TableStyle2 = "PivotStyleMedium9"
    Next pvt

End Sub

Just like the code that we have used to create a single pivot table, this code inserts a new worksheet with the name Pivot Table and then creates 8 different pivot tables on that sheet.

Then it goes to the SalesData worksheet and defines the source data that it will use to create a pivot cache.

As you have the same data source, instead of creating a pivot cache with each pivot table, this code creates a single pivot cache and then use it for creating each of the pivot tables.

And then insert eight pivot tables one by one using a different location within the worksheet so that none of the pivot table overlaps the other.

[FULL CODE] Pivot Table on the Existing Worksheet

Sub Insert_Pivot_Tables_Existing_Sheet()
    Dim wsName As String
    Dim TargetSheet As Worksheet
    Dim DSheet As Worksheet
    Dim PCache As PivotCache
    Dim PTable As PivotTable
    Dim PRange As Range
    Dim LastRow As Long, LastCol As Long
    Dim LastUsedRow As Long
    Dim InsertCell As Range

    'Ask user for the sheet name
    wsName = InputBox( _
        Prompt:="Enter sheet name to insert a pivot table.", _
        Title:="Target Sheet")


    'Check if sheet exists
    On Error Resume Next
    Set TargetSheet = ThisWorkbook.Worksheets(wsName)
    On Error GoTo 0

    If TargetSheet Is Nothing Then
        MsgBox "Sheet '" & wsName & "' does not exist.", vbExclamation
        Exit Sub
    End If

    'Set source data sheet
    Set DSheet = Worksheets("Sales_Data")

    'Define source data range
    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)

    'Check if the sheet has any content
    Dim lastCell As Range
    Set lastCell = TargetSheet.Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious)
    
    If lastCell Is Nothing Then
        'Sheet is blank, so insert at B2
        Set InsertCell = TargetSheet.Range("B2")
    Else
        'Sheet has data, insert pivot 2 rows below the last used row
        LastUsedRow = lastCell.Row
        Set InsertCell = TargetSheet.Cells(LastUsedRow + 2, 2)
    End If

    'Create Pivot Cache
    Set PCache = ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:=PRange)

    'Create the Pivot Table at the target cell with a unique name based on current time
    Set PTable = PCache.CreatePivotTable( _
    TableDestination:=InsertCell, _
    TableName:="SalesPivot_" & Format(Now, "hhmmss"))


    'Add Fields
    With PTable.PivotFields("Region")
        .Orientation = xlRowField
        .Position = 1
    End With
    With PTable.PivotFields("Salesperson")
        .Orientation = xlRowField
        .Position = 2
    End With
    With PTable.PivotFields("Product")
        .Orientation = xlColumnField
        .Position = 1
    End With
    With PTable.PivotFields("Total Sales")
        .Orientation = xlDataField
        .Function = xlSum
        .NumberFormat = "#,##0"
        .Name = "Revenue"
    End With

    'Apply style
    With PTable
        .ShowTableStyleRowStripes = True
        .TableStyle2 = "PivotStyleMedium9"
    End With

    MsgBox "Pivot Table inserted in '" & wsName & _
       "' sheet at cell " & InsertCell.Address, vbInformation
End Sub

Adding a Filter along with Creating a Pivot Table

Below are a simple lines of code that you can use while writing a code to create a pivot table that allows you to add a filter to the pivot table.

With PTable.PivotFields("Year")
    .Orientation = xlPageField
    .Position = 1
End With

Here is the complete code that can create a new pivot table and add a “Year” column as a filter for the pivot table.

Sub InsertPivotTable()
'Macro By ExcelChamps.com

'Declare Variables
    Dim PSheet As Worksheet
    Dim DSheet As Worksheet
    Dim PCache As PivotCache
    Dim PTable As PivotTable
    Dim PRange As Range
    Dim LastRow As Long
    Dim LastCol As Long

'Insert a New Blank Worksheet
    On Error Resume Next
    Application.DisplayAlerts = False
    Worksheets("PivotTable").Delete
    Application.DisplayAlerts = True
    On Error GoTo 0

    Sheets.Add Before:=ActiveSheet
    ActiveSheet.Name = "PivotTable"
    Set PSheet = Worksheets("PivotTable")
    Set DSheet = Worksheets("Sales_Data")
    
'Define Data Range
    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)
    
'Define Pivot Cache
    Set PCache = ActiveWorkbook.PivotCaches.Create( _
        SourceType:=xlDatabase, SourceData:=PRange)

'Insert Pivot Table
    Set PTable = PCache.CreatePivotTable( _
        TableDestination:=PSheet.Cells(2, 2), TableName:="SalesPivotTable")

'Insert Filter Field (Page Field)
    With PTable.PivotFields("Location")
        .Orientation = xlPageField
        .Position = 1
    End With
    
'Insert Row Fields
    With PTable.PivotFields("Region")
        .Orientation = xlRowField
        .Position = 1
    End With
    With PTable.PivotFields("Salesperson")
        .Orientation = xlRowField
        .Position = 2
    End With

'Insert Column Fields
    With PTable.PivotFields("Product")
        .Orientation = xlColumnField
        .Position = 1
    End With

'Insert Data Field
    With PTable.PivotFields("Total Sales")
        .Orientation = xlDataField
        .Function = xlSum
        .NumberFormat = "#,##0"
        .Name = "Revenue"
    End With

'Format Pivot Table
    PTable.ShowTableStyleRowStripes = True
    PTable.TableStyle2 = "PivotStyleMedium9"
    
End Sub

[SAMPLE FILES] (EC0010)

In the end,

By using this code, we can automate your pivot tables.

And the best part is this is a one-time setup; after that, we just need a click to create a pivot table, and you can save a ton of time.

Now tell me one thing.

Have you ever used a VBA code to create a pivot table?

Please share your views with me in the comment box; I’d love to share them with you and share this tip with your friends.

VBA is one of the Advanced Excel Skills, and if you are getting started with VBA, make sure to check out the Useful Macro Examples and VBA Codes.

186 thoughts on “A Step-by-Step Guide to Create a Pivot Table in Excel using VBA – MACRO CODE”

  1. how can I add mulitple pivot tables in the same sheet using the code ??

    Reply
  2. I try with the same code, Pivot sheet (In the next sheet the new sheet is added) got created.

    But the Pivot table in the new sheet is not appearing? How do I debug this?
    Can someone help me

    Reply
  3. Can someone help me?
    I have some issues in the code below. When running the macro it stops right after creating the new sheet. No error message shows up.

    ‘ insert pivot table

    ‘Declare Variables
    Dim PSheet As Worksheet
    Dim DSheet As Worksheet
    Dim PCache As PivotCache
    Dim PTable As PivotTable
    Dim PRange As Range
    Dim LastRow As Long
    Dim LastCol As Long

    ‘Insert a New Blank Worksheet
    On Error Resume Next
    Application.DisplayAlerts = False
    Worksheets(“IHOD in the past”).Delete
    Sheets.Add Before:=ActiveSheet
    ActiveSheet.Name = “IHOD in the past”
    Application.DisplayAlerts = True
    Set PSheet = Worksheets(“IHOD in the past”)
    Set DSheet = Worksheets(“DBS data”)

    ‘Define Data Range
    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)

    ‘Define Pivot Cache
    Set PCache = ActiveWorkbook.PivotCaches.Create _
    (SourceType:=xlDatabase, SourceData:=PRange). _
    CreatePivotTable(TableDestination:=PSheet.Cells(2, 2), _
    TableName:=”IHODinthepast”)

    ‘Insert Blank Pivot Table
    Set PTable = PCache.CreatePivotTable _
    (TableDestination:=PSheet.Cells(1, 1), TableName:=”IHODinthepast”)

    Reply
      • Works for me in the sample file, but when I tried to use in the actual file – all I got was an empty worksheet.

        Reply
        • Check for the fields name and worksheets name in the code.

          Reply
    • The reason you aren’t getting any error messages/alerts is because at the beginning of your code, it says “On Error Resume Next” which tells VBA to ignore any errors and to resume the code with the next line following an error. This is necessary when deleting a worksheet that may/may not exist (if the worksheet you’re deleting doesn’t yet exist, it will cause an error and will stop your code). However, after you have deleted the worksheet, you need to say “On Error Goto 0” which tells VBA to handle errors normally when they occur.

      Reply
  4. the PI suggest the following improvement to your code:
    Instead of
    ‘Define Pivot Cache
    Set PCache = ActiveWorkbook.PivotCaches.Create _
    (SourceType:=xlDatabase, SourceData:=PRange). _
    CreatePivotTable(TableDestination:=PSheet.Cells(2, 2), _
    TableName:=”SalesPivotTable”)

    it should read
    ‘Define Pivot Cache
    Set PCache = ActiveWorkbook.PivotCaches.Create _
    (SourceType:=xlDatabase, SourceData:=PRange)

    The reason is that you create a type mismatch as PCache is not a pivot table.

    Reply
  5. Hi. I used this, but it creates a new sheet but doesn’t actually insert in a pivot table….

    Sub InsertPivotTable()

    ‘Declare Variables
    Dim PSheet As Worksheet
    Dim DSheet As Worksheet
    Dim PCache As PivotCache
    Dim PTable As PivotTable
    Dim PRange As Range
    Dim LastRow As Long
    Dim LastCol As Long

    ‘Insert a New Blank Worksheet
    On Error Resume Next
    Application.DisplayAlerts = False
    Worksheets(“PivotTable”).Delete
    Sheets.Add Before:=ActiveSheet
    ActiveSheet.Name = “PivotTable”
    Application.DisplayAlerts = True
    Set PSheet = Worksheets(“PivotTable”)
    Set DSheet = Worksheets(“Data”)

    ‘Define Data Range
    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)

    ‘Define Pivot Cache
    Set PCache = ActiveWorkbook.PivotCaches.Create _
    (SourceType:=xlDatabase, SourceData:=PRange). _
    CreatePivotTable(TableDestination:=PSheet.Cells(2, 2), _
    TableName:=”OutOfPocketSpend”)

    ‘Insert Blank Pivot Table
    Set PTable = PCache.CreatePivotTable _
    (TableDestination:=PSheet.Cells(1, 1), TableName:=”OutOfPocketSpend”)

    ‘Insert Row Fields
    With ActiveSheet.PivotTables(“OutOfPocketSpend”).PivotFields(“Sales Order Facility”)
    .Orientation = xlRowField
    .Position = 1
    End With

    ‘Insert Column Fields
    With ActiveSheet.PivotTables(“OutOfPocketSpend”).PivotFields(“Status”)
    .Orientation = xlColumnField
    .Position = 1
    End With

    ‘Insert Data Field
    With ActiveSheet.PivotTables(“OutOfPocketSpend”).PivotFields(“Sales Order Detail Extended Allowance Amount”)
    .Orientation = xlDataField
    .Position = 1
    .Function = xlSum
    .NumberFormat = “$#,##0”
    .Name = “Revenue ”
    End With

    ‘Format Pivot
    TableActiveSheet.PivotTables(“OutOfPocketSpend”).ShowTableStyleRowStripes = TrueActiveSheet.PivotTables(“OutOfPocketSpend”).TableStyle2 = “PivotStyleMedium9”

    Reply
  6. Very informative – will return to your website blogs again

    Reply
  7. Hello, I was wondering how you would change this if your values do not start a 1,1. I have been trying but it has not been working.

    Reply
  8. SUPER EXPLANATION. GREATLY APPRECIATED

    Reply
  9. This has been extremely helpful in fixing a broken code that I have in a creating a pivot table. The question I have, what is the proper code if the title of your columns change? I am working on a manufacturing capacity outlook file that changes weekly. I need to have my column names in my pivot table change to the upcoming weeks.
    So instead of: ActiveSheet.PivotTables(“PivotTable5”).AddDataField ActiveSheet.PivotTables( _
    “PivotTable5”).PivotFields(“19-Oct-21”), “Sum of 19-Oct-21”, xlSum
    I need: ActiveSheet.PivotTables(“PivotTable5”).AddDataField ActiveSheet.PivotTables( _
    “PivotTable5”).PivotFields(E2), “Sum of “E2, xlSum
    But I get an error message Expected: end of statement with E2 highlighted after “Sum of”.

    Reply
    • I know this is super late, but maybe this will help someone else with a similar question:

      VBA doesn’t recognize E2 as a range by itself, so it doesn’t know what you’re referring to. Instead you could write it as:
      .PivotFields(Range(“E2”))
      When you’re attaching a string (text) to something like a range reference, you must insert an ‘&’ in between so that VBA knows to combine the two types of variables into one. For example:
      “Sum of ” & Range(“E2”)

      Reply
  10. Awesome. It really helps to enhance my knowledge of VBA. Now new challenge – filtering.

    Reply
  11. Dear ExcelChamps,

    Your code worked perfectly fine for me.
    I was able to create the pivot table using the VBA. However, I have a requirement to get the pivot table in the classical view and also with subtotals removed. Now I am doing this manually after generating the pivot table using your code. Is it possible to convert the pivot table in to classical view and remove subtotals using VBA? Kindly guide me for the same if it is possible.
    Thanks in advance.

    Reply
    • to help figure out the code, record your actions when changing the pivot table in classical view and subtotals removed. the macro created will contain the code to automate it

      Reply
  12. For anyone having issues with the Values field, it looks like moving the .PivotFields up to the first line of the With statement makes it work, e.g.:

    With ActiveSheet.PivotTables(“SalesPivotTable”).PivotFields (“Amount”)
    .Orientation = xlDataField
    .Function = xlSum
    .NumberFormat = “#,##0”
    .Name = “Revenue ”
    End With

    Reply

Leave a Comment