vba excel - Pivot Tablle Calculated Field - vba

I have developed a Pivot Table and need to add a calculated field. Rather than using the 'named' (row) fields, I would like to use the 'reference' field in my calculation. The formula works fine using the 'named' field. but not when using a 'reference'. Below is part of the code and where is goes wrong. Appreciate your guidance and help.
'/-------------
'/ Insert Data Field
'/-------------
With pTable
With .PivotFields(wksDSheet.Cells(1, 5).Value)
.Orientation = xlDataField
.Position = 1
.Function = xlSum
'NumberFormat = "#,##0.00"
.Caption = "Actual Spent"
End With
s1 = pTable.PivotFields(wksDSheet.Cells(1, 5).Value)
With .PivotFields(wksDSheet.Cells(1, 6).Value)
.Orientation = xlDataField
.Position = 2
.Function = xlSum
'.NumberFormat = "#,##0.00"
.Caption = "YmBudget To date"
End With
With .PivotFields(wksDSheet.Cells(1, 7).Value)
.Orientation = xlDataField
.Position = 3
.Function = xlSum
'.NumberFormat = "#,##0.00"
.Caption = "YrBudget To Year"
s2 = pTable.PivotFields(wksDSheet.Cells(1, 7).Value)
End With
End With
'/-------------------
'/ Insert Calculated Fields
'/-------------------
'/ The Name and Formula
''' This works''''>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
' pTable.CalculatedFields.Add Name:="Available", _
Formula:="=YrBudget - Actual"
''' This does NOT work ''''>>>>>>>>>>>>>>>>>>>>>>>>
pTable.CalculatedFields.Add Name:="Available", _
Formula:="=s2 - s1"
With pTable.PivotFields("Available")
.Orientation = xlDataField
.Function = xlSum
.Position = 4
'.NumberFormat = "0.00"
.Caption = "Net Available"
End With

Related

How to use AverageIf function in excel macro

The below code does not work. I am trying to create a pivot with average of Hrs and I don't want the value 0 to be considered in the average.
With ActiveSheet.PivotTables("AnalyticsPivotTable").PivotFields("Hrs")
.Orientation = xlDataField
.Position = 2
.Function = "=AverageIf(M:M,"">0"")"
.NumberFormat = "#,##0"

Error 440: Method 'Create' of object 'PivotCaches' failed

I have been trying to create a macro that populates a pivot table. However, I keep getting this
Run-Time Error 440
on the Set Cache line.
Previously, I was running into other run time errors but those were easy fixes. I do not understand why the PivotCaches.Create method is not allowed in this case. SOS, please help!
Here is the code:
' Declare variables for pivots
Dim pivotWB As Workbook
Dim RawDataWS As Worksheet
Dim dataLocation As Range
Dim cache As PivotCache
Dim table As PivotTables
' name and set the workbook for pivot tables
folderName = ThisWorkbook.Sheets(1).Cells(5, 13).Value
fileName = ThisWorkbook.Sheets(1).Cells(6, 13).Value
extName = ThisWorkbook.Sheets(1).Cells(7, 13).Value
wbAddress = folderName & "\" & fileName & "." & extName
Set pivotWB = Workbooks.Open(wbAddress)
Set dataLocation = pivotWB.Sheets("Raw Data").Range("A:AK")
Set cache = pivotWB.PivotCaches.Create(SourceType:=xlDatabase,_
sourceData:=dataLocation, Version:=xlPivotTableVersion14)
For i = 1 To 5
' create new worksheet and pivot table
pivotWB.Sheets.Add Before:=Sheets(1)
pivotWB.Sheets(1).Name = Left(toPivot(i), 30)
cache.CreatePivotTable TableDestination:=pivotWB.Sheets(1).Cells(1, 1), TableName:=toPivot(i) & " Pivot Table"
' set rows
With pivotWB.Sheets(1).PivotTables(toPivot(i) & " Pivot Table").PivotFields("Rejection Category Description")
.Orientation = xlRowField
.Position = 1
End With
' set columns
With pivotWB.Sheets(1).PivotTables(toPivot(i) & " Pivot Table").PivotFields("Post Period")
.Orientation = xlColumnField
.Position = 1
End With
' set values
With pivotWB.Sheets(1).PivotTables(toPivot(i) & " Pivot Table").PivotFields("Procedure Code")
.Orientation = xlDataField
.Position = 1
.Function = xlCount
.NumberFormat = "#,##0"
.Name = "Count of Code"
End With
With pivotWB.Sheets(1).PivotTables(toPivot(i) & " Pivot Table").PivotFields("Amount")
.Orientation = xlDataField
.Position = 2
.Function = xlSum
.NumberFormat = "$#,##0"
.Name = "Sum of Amount"
End With
Next i
Following #Rory comment, you need to set the PivotCache object using the Address property.
Also, setting your table object to your PivotTable will create a much easier and shorter code.
See code below, more notes inside the code's comments.
Modified Code
' --- set the Pivot Cache ---
Set cache = pivotWB.PivotCaches.Create(SourceType:=xlDatabase, _
SourceData:=dataLocation.Address(False, False, xlR1C1, xlExternal))
For i = 1 To 5
' create new worksheet and pivot table
pivotWB.Sheets.Add Before:=Sheets(1)
pivotWB.Sheets(1).Name = Left(toPivot(i), 30)
' --- set the Pivot-Table Object ---
Set table = cache.CreatePivotTable(TableDestination:=pivotWB.Sheets(1).Cells(1, 1), TableName:=toPivot(i) & " Pivot Table")
With table ' <-- after you set the table object, you can simply use With statement now
' set rows
With .PivotFields("Rejection Category Description")
.Orientation = xlRowField
.Position = 1
End With
' set columns
With .PivotFields("Post Period")
.Orientation = xlColumnField
.Position = 1
End With
' set values
With .PivotFields("Procedure Code")
.Orientation = xlDataField
.Position = 1
.Function = xlCount
.NumberFormat = "#,##0"
.Name = "Count of Code"
End With
With .PivotFields("Amount")
.Orientation = xlDataField
.Position = 2
.Function = xlSum
.NumberFormat = "$#,##0"
.Name = "Sum of Amount"
End With
End With
Next i

Error while creating Pivot Table automatically

I have created a macro to create a table with some values via Index matches and general calculations. This table is located on the range("AA1:BA"&LastRow) --> I am writing LastRow because the lastrow changes daily. I want to create a pivot table which will be located in the cell(9,1) and will have as a source the initial table that I created.. I built the code that you see below, but it gives me an error saying that the PivotTable field name is not valid on the line :
Set PCache = ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:=PRange).CreatePivotTable(TableDestination:=PSheet.Cells(2, 2), TableName:="PivotTable")
The entire code related to the Pivot Table is below.
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
Application.DisplayAlerts = False
Application.DisplayAlerts = True
Set PSheet = Worksheets("Budget_Report")
Set DSheet = Worksheets("Budget_Report")
LastRow = DSheet.Cells(Rows.Count, 27).End(xlUp).Row
LastCol = DSheet.Cells(1, Columns.Count).End(xlToLeft).Column
Set PRange = DSheet.Cells(1, 27).Resize(LastRow, LastCol)
Set PCache = ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:=PRange)
Set PTable = PCache.CreatePivotTable(TableDestination:=PSheet.Cells(9, 1), TableName:="PivotTable")
With ActiveSheet.PivotTables("PivotTable").PivotFields("T-Lane")
.Orientation = xlRowField
.Position = 1
.Subtotals(1) = True
.Subtotals(1) = False
End With
With ActiveSheet.PivotTables("PivotTable").PivotFields("Monthly Cost FCST")
.Orientation = xlDataField
.Position = 1
.Function = xlSum
.Name = "Monthly Cost Forecast"
End With
With ActiveSheet.PivotTables("PivotTable").PivotFields("Monthly Vol FCST")
.Orientation = xlDataField
.Position = 2
.Function = xlSum
.Name = "Monthly Vol Forecast"
End With
With ActiveSheet.PivotTables("PivotTable").PivotFields("Monthly $/SU FCST")
.Orientation = xlDataField
.Position = 3
.Function = xlSum
.Name = "Monthly $/SU Forecast"
End With
With ActiveSheet.PivotTables("PivotTable").PivotFields("Monthly Cost Actuals")
.Orientation = xlDataField
.Position = 4
.Function = xlSum
.Name = "Monthly Cost Actual"
End With
With ActiveSheet.PivotTables("PivotTable").PivotFields("Monthly Vol Actuals")
.Orientation = xlDataField
.Position = 5
.Function = xlSum
.Name = "Monthly Vol Actual"
End With
With ActiveSheet.PivotTables("PivotTable").PivotFields("Monthly $/SU Actuals")
.Orientation = xlDataField
.Position = 6
.Function = xlSum
.Name = "Monthly $/SU Actual"
End With
The recorded macro that builds the Pivot Table is provided below (it has specific range not lastrow and lastcolumn of course)
ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:="Budget_Report!R1C27:R279C53", Version:=6).CreatePivotTable TableDestination:="Budget_Report!R9C1", TableName:="PivotTable1", DefaultVersion:=6
Sheets("Budget_Report").Cells(9, 1).Select
With ActiveSheet.PivotTables("PivotTable1").PivotFields("T-Lane")
.Orientation = xlRowField
.Position = 1
End With
ActiveSheet.PivotTables("PivotTable1").AddDataField ActiveSheet.PivotTables("PivotTable1").PivotFields("Monthly Cost FCST"), "Monthly Cost Forecast", xlSum
ActiveSheet.PivotTables("PivotTable1").AddDataField ActiveSheet.PivotTables("PivotTable1").PivotFields("Monthly Vol FCST"), "Monthly Vol Forecast", xlSum
ActiveSheet.PivotTables("PivotTable1").AddDataField ActiveSheet.PivotTables("PivotTable1").PivotFields("Monthly $/SU FCST"), "Monthly $/SU Forecast", xlSum
ActiveSheet.PivotTables("PivotTable1").AddDataField ActiveSheet.PivotTables("PivotTable1").PivotFields("Monthly Cost Actuals"), "Monthly Cost Actual", xlSum
ActiveSheet.PivotTables("PivotTable1").AddDataField ActiveSheet.PivotTables("PivotTable1").PivotFields("Monthly Vol Actuals"), "Monthly Vol Actual", xlSum
ActiveSheet.PivotTables("PivotTable1").AddDataField ActiveSheet.PivotTables("PivotTable1").PivotFields("Monthly $/SU Actuals"), "Monthly $/SU Actual", xlSum
ActiveWorkbook.ShowPivotTableFieldList = False
When setting the PRange you can use Cells.SpecialCells method to set your range even though you don't always know what that end address will be as long as you're sure you won't have extra data somewhere below/beyond your target range.
It would look something like this:
Set PRange = DSheet.Range(DSheet.Cells(1, 27), DSheet.Cells.SpecialCells(xlCellTypeLastCell))
Also, it is a matter of personal style, but I find that nesting With blocks sometimes results in more readable code. Eg:
With ActiveSheet.PivotTables("PivotTable1")
With .PivotFields("Field 1")
.Caption = "My first field"
.Function = xlSum
End With
With .PivotFields("Field 2")
.Caption = "My second field"
.Function = xlMax
End With
End With
etc.
The final product looks something like this:
Dim DSheet As Worksheet ', PSheet As Worksheet
Dim PCache As PivotCache, PTable As PivotTable, PRange As Range
'Dim LastRow As Long, LastCol As Long
'Application.DisplayAlerts = False ' This is redundant since you're setting it to true below.
Application.DisplayAlerts = True
'Set PSheet = Worksheets("Budget_Report") '
Set DSheet = Worksheets("Budget_Report") ' These two are Redundant - I am using only DSheet.
'LastRow = DSheet.Cells(Rows.Count, 27).End(xlUp).Row
'LastCol = DSheet.Cells(1, Columns.Count).End(xlToLeft).Column
Set PRange = DSheet.Range(Cells(1, 27),Cells.SpecialCells(xlCellTypeLastCell))
Set PCache = ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:=PRange)
Set PTable = PCache.CreatePivotTable(TableDestination:=DSheet.Cells(9, 1), TableName:="PivotTable")
With ActiveSheet.PivotTables("PivotTable")
With .PivotFields("T-Lane")
.Orientation = xlRowField
.Position = 1
.Subtotals(1) = True ' You're resetting this value in the next line, you can probably remove it.
.Subtotals(1) = False
End With
With .PivotFields("Monthly Cost FCST")
.Orientation = xlDataField
.Position = 1
.Function = xlSum
.Caption = "Monthly Cost Forecast" 'You want .Caption here, not .Name
End With
With .PivotFields("Monthly Vol FCST")
.Orientation = xlDataField
.Position = 2
.Function = xlSum
.Caption = "Monthly Vol Forecast"
End With
With .PivotFields("Monthly $/SU FCST")
.Orientation = xlDataField
.Position = 3
.Function = xlSum
.Caption = "Monthly $/SU Forecast"
End With
With .PivotFields("Monthly Cost Actuals")
.Orientation = xlDataField
.Position = 4
.Function = xlSum
.Caption = "Monthly Cost Actual"
End With
With .PivotFields("Monthly Vol Actuals")
.Orientation = xlDataField
.Position = 5
.Function = xlSum
.Caption = "Monthly Vol Actual"
End With
With .PivotFields("Monthly $/SU Actuals")
.Orientation = xlDataField
.Position = 6
.Function = xlSum
.Caption = "Monthly $/SU Actual"
End With
End With
It appears that you try to create the same table twice:
Set PCache = ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:=PRange).CreatePivotTable(TableDestination:=PSheet.Cells(2, 2), TableName:="PivotTable")
Set PTable = PCache.CreatePivotTable(TableDestination:=PSheet.Cells(9, 1), TableName:="PivotTable")
Just split it in two:
Set PCache = ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:=PRange)
Set PTable = PCache.CreatePivotTable(TableDestination:=PSheet.Cells(9, 1), TableName:="PivotTable")
Assign to PCache only Cache:
Set PCache = ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:=PRange)

VBA code for creating Pivot Table

I have created a macro that builds a pivot table. It runs great but I want to dismiss the circled content in the screenshot provided .. I dont want to have the total inside the pivot. Only at the bottom the Grand Total! I am providing my code and a screenshot. Moreover, is it possible to substitute the "Row Labels" text in column B with "FDD"?
Sub aa()
'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("Customs_report").Delete
Sheets.Add Before:=ActiveSheet
ActiveSheet.Name = "Customs_report"
Application.DisplayAlerts = True
Set PSheet = Worksheets("Customs_report")
Set DSheet = Worksheets("Zeikan")
'Define Data Range
LastRow = DSheet.Cells(Rows.Count, 1).End(xlUp).Row
LastCol = DSheet.Cells(6, Columns.Count).End(xlToLeft).Column
Set PRange = DSheet.Cells(6, 1).Resize(LastRow, LastCol)
'Define Pivot Cache
Set PCache = ActiveWorkbook.PivotCaches.Create _
(SourceType:=xlDatabase, SourceData:=PRange). _
CreatePivotTable(TableDestination:=PSheet.Cells(2, 2), _
TableName:="PivotTable")
'Insert Blank Pivot Table
Set PTable = PCache.CreatePivotTable _
(TableDestination:=PSheet.Cells(1, 1), TableName:="PivotTable")
'Insert Row Fields
With ActiveSheet.PivotTables("PivotTable").PivotFields("Commodity Code")
.Orientation = xlRowField
.Position = 1
.Name = "Commodity Code"
End With
With ActiveSheet.PivotTables("PivotTable").PivotFields("Location")
.Orientation = xlRowField
.Position = 2
End With
'Insert Column Fields
With ActiveSheet.PivotTables("PivotTable").PivotFields("Quantity (cases/sw)")
.Orientation = xlDataField
.Position = 1
.Function = xlSum
.Name = "Sum of Quantity (cases/sw)"
End With
With ActiveSheet.PivotTables("PivotTable").PivotFields("Quantity (items)")
.Orientation = xlDataField
.Position = 2
.Function = xlSum
.Name = "Sum of Quantity (items)"
End With
With ActiveSheet.PivotTables("PivotTable").PivotFields("Net value")
.Orientation = xlDataField
.Position = 3
.Function = xlSum
.Name = "Sum of Net value"
End With
With ActiveSheet.PivotTables("PivotTable").PivotFields("Gross weight (Kg)")
.Orientation = xlDataField
.Position = 4
.Function = xlSum
.Name = "Sum of Gross weight (Kg)"
End With
With ActiveSheet.PivotTables("PivotTable").PivotFields("Net weight (Kg)")
.Orientation = xlDataField
.Position = 5
.Function = xlSum
.Name = "Sum of Net weight (Kg)"
End With
End Sub
You can toggle the subtotals:
With PTable.PivotFields("Commodity Code")
.Orientation = xlRowField
.Position = 1
.Name = "Commodity Code"
.Subtotals(1) = True
.Subtotals(1) = False
End With
to change the header, change the table layout to tabular
PTable.LayoutRowDefault = xlTabularRow
before you add the fields. BTW, you should be using PTable rather than ActiveSheet.PivotTables("PivotTable") in the rest of your code.

Inserting a date from a cell into a Pivot table to use it as a filter

Im very new to VBA. I will explain my project.
I have an Excel sheet with a lot of information that I want to filter. For the moment my code looks like this:
With ActiveSheet.PivotTables("Tableau croisé dynamique2").PivotFields( _
"CREATION_DATE")
.Orientation = xlPageField
.Position = 1
End With
ActiveSheet.PivotTables("Tableau croisé dynamique2").AddDataField ActiveSheet. _
PivotTables("Tableau croisé dynamique2").PivotFields("AMOUNT"), _
"Nombre de AMOUNT", xlCount
With ActiveSheet.PivotTables("Tableau croisé dynamique2").PivotFields("STATUS")
.Orientation = xlRowField
.Position = 1
End With
With ActiveSheet.PivotTables("Tableau croisé dynamique2").PivotFields( _
"VENDOR_NAME")
.Orientation = xlRowField
.Position = 2
End With
With ActiveSheet.PivotTables("Tableau croisé dynamique2").PivotFields( _
"INVOICE_NUM")
.Orientation = xlRowField
.Position = 3
End With
With ActiveSheet.PivotTables("Tableau croisé dynamique2").PivotFields( _
"Nombre de AMOUNT")
.Caption = "Somme de AMOUNT"
.Function = xlSum
End With
ActiveSheet.PivotTables("Tableau croisé dynamique2").PivotFields( _
"CREATION_DATE").CurrentPage = "08/09/2016"
This code works to extract to filter with the date 08/09/2016.
Now, I would like to make the pivot table get this date in a cell ahead of launching the code.
But I don't want to have to go in to the code every time to change the date I want.
I would like something like this:
Ex: I write "09/09/2016" in cell "A1"
ActiveSheet.PivotTables("Tableau croisé dynamique2").PivotFields( _
"CREATION_DATE").CurrentPage = "A1"
But I am getting a debugging error.
After some testing, I found the cause (on my Excel Book). It was related to formatting the Pivot Field "CREATION_DATE", once I added the following section it worked.
Set PvtFld = PvtTbl.PivotFields("CREATION_DATE")
With PvtFld
.Orientation = xlPageField
.NumberFormat = "dd/mm/yyyy" ' << this line
.Position = 1
End With
And for the full code:
Sub PivotFilterDate()
Dim PvtTbl As PivotTable
Dim PvtFld As PivotField
' set your Pivot Table (after created) to a variable
Set PvtTbl = Sheets("PivotSpanish").PivotTables("Tableau croisé dynamique2")
' Set "CREATION_DATE" to a Pivot Field variable
Set PvtFld = PvtTbl.PivotFields("CREATION_DATE")
With PvtFld
.Orientation = xlPageField
.NumberFormat = "dd/mm/yyyy"
.Position = 1
End With
' you can modify your code to change all field setting, like following 2:
With PvtTbl.PivotFields("STATUS")
.Orientation = xlRowField
.Position = 1
End With
With PvtTbl.PivotFields("VENDOR_NAME")
.Orientation = xlRowField
.Position = 2
End With
' clear previous filters
PvtFld.ClearAllFilters
' --- trapping errors ---
' added a Boolean Flag to trap scenarios where no Pivot Item found that matches the value in Cell A1
Dim PvtItemExists As Boolean
PvtItemExists = False
' check all Pivot items in Pivot Field ("CREATION_DATE")
For Each PvtItem In PvtFld.PivotItems
' check if current Pivot Item equals the value in Cell A1
If PvtItem.Value = CStr(CDate(Range("D1").Value)) Then
PvtItemExists = True
Exit For
End If
Next PvtItem
If PvtItemExists Then
PvtFld.CurrentPage = CStr(CDate(Range("D1").Value))
Else
MsgBox "No data matches for date " & CDate(Range("D1").Value) & " in Pivot Table", vbCritical
End If
End Sub