Creating pivot table with macro - subscript out of range - vba

I am trying to create pivot table macro. For this, I have input data and I have a recorded macro on it. However, I am getting an error since I want to use it in multiple areas of the code.
Here is some sample data:
I need output like this:
Sub macro5()
'
' macro5 Macro
'
'
Range("A2:C16").Select
Range("C16").Activate
Sheets.Add
ActiveWorkbook.Worksheets("sheet2").PivotTables("PivotTable3").PivotCache. _
CreatePivotTable TableDestination:="Sheet6!R3C1", TableName:="PivotTable5" _
, DefaultVersion:=xlPivotTableVersion12
Sheets("Sheet6").Select
Cells(3, 1).Select
With ActiveSheet.PivotTables("PivotTable5").PivotFields("Item")
.Orientation = xlRowField
.Position = 1
End With
With ActiveSheet.PivotTables("PivotTable5").PivotFields("Category")
.Orientation = xlColumnField
.Position = 1
End With
ActiveSheet.PivotTables("PivotTable5").AddDataField ActiveSheet.PivotTables( _
"PivotTable5").PivotFields("Price"), "Sum of Price", xlSum
End Sub
I am getting an error at the highlighted part.
Can anyone help me figure out why?

Your code only works if there is already an existing pivot table from the same dataset on Sheet2, called PivotTable3. Pivot tables share a PivotCache, and if one exists, Excel won't create another, but reuse the existing. That is what your macro is trying to do.
I suggest recording a macro with no pivot table in your document. That way the pivot-cache-creating-code will appear in the recorded macro. If you need multiple pivot tables, then you can use the above macro for the next pivot tables, but make sure to point to your first pivot table's cache.
What you must consider when recording a macro to insert pivot tables:
Notice that the macro recorder recorded some fixed names (e.g. sheet names, pivot table names, data input area). Make sure these are correct, and if not, make them dynamic with variables or otherwise.
Here is a sample code for creating a new pivot table:
ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:= _
"Sheet2!R1C1:R9C3", Version:=xlPivotTableVersion15).CreatePivotTable _
TableDestination:="Sheet3!R3C1", TableName:="PivotTable1", DefaultVersion:=xlPivotTableVersion15
Notice how it is different form yours.
Now about the problematic parts:
SourceData:="Sheet2!R1C1:R9C3"
If you want your source data to be dynamic, change this. E.g. to make it use your current selection, use this:
SourceData:=Selection
Another interesting part:
TableDestination:="Sheet3!R3C1"
If you just use empty string (""), it will always insert the pivot table on a new sheet (which will also be activated immediately):
TableDestination:=""
The name of the pivot table is not a problem, as from Excel 2007 and up, you can have multiple pivot tables with the same name, as long as they are on different sheets. If you want more pivot tables on the same sheet, you will have to mind the TableName property too.
OK, I could go on about this for many pages. I hope this helps! If you have questions, do ask.

Related

How to "Add this data to the data model?" and make data in values distinct?

I am using Excel 2016, and I have the code to create a PivotTable from my data set. However, I'm not sure how to include the data in the data model (which is an option you see when clicking on "PivotTable" from the Insert Tab.
My goal is to have a Distinct Count of my variable that I'm using in the Values data field.
With PvtTbl.PivotFields("sid")
.Orientation = xlDataField
.Function = xlSum
.NumberFormat = "#,##0"
.Position = 1
I tried replacing "xlSum" with "xlDistinct" but of course that would be too easy haha.
Please note that vba coding with data model pivot is totally different than pivot sourced by normal data range, You may use such below code after empty the data field:
With PvtTbl
.AddDataField .CubeFields("[Measures].[Distinct Count of sid]"), "Distinct Count of sid"
End With

How to select data range dynamically for pivot table

I have searched this topic exhaustively however I am struggling to find a solution which works for my macro. I need the source data for a pivot table to include all rows (containing data) on a sheet. The amount of rows will change daily.
Here is what I've got so far:
Sheets("Sheet1").Select
Sheets("Sheet1").Name = "RAW_DATA"
Range("A1").Select
Sheets.Add
ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:= _
"RAW_DATA!R1C1:R159C24", Version:=xlPivotTableVersion14).CreatePivotTable _
TableDestination:="Sheet4!R3C1", TableName:="PivotTable1", DefaultVersion _
:=xlPivotTableVersion14
Sheets("Sheet4").Select
Cells(3, 1).Select
With ActiveSheet.PivotTables("PivotTable1").PivotFields("Asset")
.Orientation = xlRowField
.Position = 1
End With
The values which represent my pivot tables source data are RAW_DATA!R1C1:R159C24. The problem is that I need this range to dynamically increase or decrease depending on the size of the populated source data range.
First of all, you might be able to easily solve your problem by just setting the columns as your datarange (E.g. RAW_DATA!$A:$X).
When the data is appended a simple update on the pivot will include new data or exclude the data that is no longer there.
That said, here's a VBA solution:
This Example will change the source data for PivotTable1 on Sheet1 to be "RAW_DATA!$A$1:$X$ whatever the last row is"
Sub ChangePivotData()
Dim lastrow as double
lastrow = Worksheets("RAW_DATA").Range("A" & Rows.Count).End(xlUp).Row
With Worksheets("Sheet1").PivotTables("PivotTable1")
.ChangePivotCache ActiveWorkbook.PivotCaches.Create( _
SourceType:=xlDatabase, _
SourceData:="RAW_DATA!A2:X" & CStr(lastrow), _
Version:=xlPivotTableVersion14)
End With
End Sub
That is the core of it. However, you might want to check for blank column headers to do some error prevention, automatically refresh the table after the new cache has been set, etc.
More extensive example can be found here:
http://www.thespreadsheetguru.com/the-code-vault/2014/7/9/change-a-pivot-tables-data-source-range
Enjoy :)
You can use the below if your data is the only thing in the sheet
Worksheets("RAW_DATA").Usedrange
and the corresponding range address
Worksheets("RAW_DATA").Usedrange.Address
Hope this helps

Use a loop to delete data in a table range from multiple tables with like names

I'd like to setup a macro to remove data from a range within a group of data tables that may change dynamically. For instance, the spreadsheet currently contains 16 data tables listed as L2_1, L2_2, L2_3.....L2_16. I'd like the macro to be flexible enough to be able to expand or contract if the number of tables changes in the sheet. I would also like to delete just the range[L2 number] within the table (this is the same range name for all of the tables).
There are also another type of tables that increment in the sheet as well ("L3L2_1, L3L2_2....L3L2_16). I'd like the macro to ignore these tables. Below is what I have started, but I receive a "1004" error at the clear contents line.
Sub Summary_II_Clear_Contents()
' Clears Summary II Tab
Dim tbl As ListObject
i = 1
For Each tbl In Sheets("Summary II").ListObjects
If tbl.Name Like "L2_" & i Then
Sheets("Summary II").Range("L2_&i&[L2 Number]").ClearContents
i = i + 1
End If
Next tbl
End Sub
Thanks for the help!
I think you just need to fix your If statement.
Also, you need to decide what For Loop construct to use.
If you decide to go with the For Each construct:
For Each tbl In Sheets("Summary II").ListObjects
If InStr(tbl.Name, "L2_") = 1 Then
Sheets("Summary II").Range(tbl.Name & "[L2 Number]").ClearContents
End If
Next tbl
Now, you can also use the classic For Next construct:
With Sheets("Summary II")
For i = 1 To .ListObjects.Count
If InStr(.ListObjects(i).Name, "L2_") = 1 Then
.Range(.ListObjects(i).Name & "[L2 Number]").ClearContents
End If
Next tbl
End With
Take note that we incorporated a With Clause just to make it look clean. HTH.

Adjusting Tables

I am trying to create a macro using VB that will convert many rows of data into a table. I want to store this macro and run it again and again. The one issue is that each time I will run it, there will be a different amount of rows.
The code I am using now is:
'CREATE NEW TABLE
Sub CreateTable2()
ActiveSheet.ListObjects.Add(xlSrcRange, Range("$A$1:$H$922"), , xlYes).Name = _
"MyNewTable2"
'No go in 2003
ActiveSheet.ListObjects("MyNewTable2").TableStyle = "TableStyleLight2"
End Sub
The above code will only go as far as '922' rows. I am looking for a way that can adjust to the amount of rows each time.
What you can do is construct the range using Range.End().
ActiveSheet.ListObjects.Add(xlSrcRange, _
Range("$A$1:$H$" & Range("H1").End(xlDown).Row), , xlYes).Name = "MyNewTable2"

Application-defined or object-defined error

So I have a sheet called "Dashboard" that I have several charts on, but every week I'm adding data to the tables these charts are based on. The second sheet that has the data for this table is "Historical Totals" and the data I want is in columns A through E (this includes labels and headers). I'm trying to automate the charts updating, and I don't quite know why this isn't working. Here is the code I have so far:
Sheets("Dashboard").Select
ActiveSheet.ChartObjects("Chart 4").Activate
ActiveChart.SetSourceData Source:=Sheets("Historical Totals").Range("A1", Range("E1").End(xlDown))
I've tried seperating our the range, and it is selecting the appropriate data, so I don't really know where I'm making the mistake.
try the following. You need to reference the data sheet every time you use Range:
Sheets("Dashboard").ChartObjects("Chart 4").Activate
ActiveChart.SetSourceData _
Source:=Sheets("Historical Totals").Range(Sheets("Historical Totals").Range("A1"), _
Sheets("Historical Totals").Range("E1").End(xlDown))
Assuming you only have the table in the worksheet "Historical Totals" I would usually go xlUp rather than xlDown but the following is effectively the same as Philip A Barnes's answer:
Sub setArea()
With Excel.ActiveWorkbook
'.Sheets("Dashboard").Select '<==no need to select for the code to execute
.Sheets("Dashboard").ChartObjects("Chart 1").Activate
End With
With Excel.ActiveWorkbook.Sheets("Historical Totals")
Excel.ActiveChart.SetSourceData _
Source:=.Range( _
.Cells(1, 1), _
.Cells(.Cells(.Rows.Count, 5).End(Excel.xlUp).Row, 5) _
)
End With
End Sub