VBA: Runtime Error - SetSourceData for Second Pivot Chart - vba

I am getting:
Run-time error '-2147467259 (80004005)':
Method 'SetSourceData' of object '_Chart' failed
intermittently when I try to run the following script:
Sub CreatePiePivot()
'Define worksheets
Set PSheet = Sheets("Tools")
Set DSheet = Sheets("Aggregate")
'Define last data points
LastRow = DSheet.Cells(Rows.Count, 1).End(xlUp).Row
LastCol = DSheet.Cells(1, Columns.Count).End(xlToLeft).Column
'Selects first to last filled row, and first to last filled column for data
Set PRange = DSheet.Cells(1, 1).Resize(LastRow, LastCol)
'Create pivot cache
Set PCache = ActiveWorkbook.PivotCaches.Create _
(SourceType:=xlDatabase, SourceData:=PRange)
'Moves user to Dashboard
Sheets("Tools").Activate
'Create blank pivot table
Set PTable = PCache.CreatePivotTable _
(TableDestination:=PSheet.Range("F1"), _
TableName:="ExcPT1")
'Create blank pivot chart
PSheet.Shapes.AddChart.Select
ActiveChart.ChartType = xlPie
ActiveChart.SetSourceData _
Source:=Range("$F$2:$H$19"), _
PlotBy:=xlRows
ActiveWorkbook.ShowPivotTableFieldList = False
With ActiveChart.PivotLayout.PivotTable.PivotFields("Exception")
.Orientation = xlRowField
.Position = 1
End With
'Insert Data
With PSheet.PivotTables("ExcPT1").PivotFields("Exception")
.Orientation = xlDataField
.Position = 1
.Caption = "Exception Status Count"
.Function = xlCount
End With
'Hide Not Due
With ActiveChart.PivotLayout.PivotTable.PivotFields("Exception Status")
.PivotItems("Not due").Visible = False
End With
'Move bar chart to Dashboard; resize
ActiveChart.ChartArea.Select
ActiveChart.Location Where:=xlLocationAsObject, Name:="Dashboard"
Set ChartWidth = Sheets("Dashboard").Range("B26:L49")
With ActiveChart.Parent
.Height = ChartWidth.Height
.Width = ChartWidth.Width
.Top = ChartWidth.Top
.Left = ChartWidth.Left
End With
With ActiveChart
.HasTitle = False
End With
End Sub
This sub is running after another very similar sub that creates a pivot bar chart using a sub connected to a button:
Sub CreatePivots()
Call CreateBarPivot
Call CreatePiePivot
End Sub
The BarPivot runs perfectly, no problem, every time, and looks almost identical to the PiePivot shown above with the applicable changes to display the appropriate data. If I run those subs separately, it usually runs without a problem. I ran-and-deleted the sub and results three times before I got the error. The debug is pointing at this line:
ActiveChart.SetSourceData _
Source:=Range("$F$2:$H$19"), _
PlotBy:=xlRows
...but it looks exactly like the one used by the BarPivot. Since it's not happening exactly every time, but most of the time, I'm not sure where to start on troubleshooting. The documentation I've looked up (which is sparse by the way, or I'm looking in the wrong places) indicates I'm doing this right.
What's causing the error, and how do I fix it?

This is an example to illustrate how to avoid using Select and Activate in your code, plus a few other (hopefully useful) comments.
Always Use Option Explicit - this can't be emphasized enough
This will turn the first few lines of your Sub into:
Option Explicit
Sub CreatePiePivot()
Dim thisWB As Workbook
Set thisWB = ThisWorkbook
Dim PSheet As Worksheet
Dim DSheet As Worksheet
Set PSheet = thisWB.Sheets("Tools")
Set DSheet = thisWB.Sheets("Aggregate")
Notice that by defining thisWB, you're setting up a workbook reference in a single line that, if you ever needed to change workbooks, change that one line and you're done. Also, this reference can explain why you should use ThisWorkbook over ActiveWorkbook.
Because some of your issues involve assumed references (either workbooks or worksheets or charts), the next lines can help show some necessary references that are easy to miss:
'Define last data points
Dim lastRow As Long
Dim lastCol As Long
lastRow = DSheet.Cells(DSheet.Rows.Count, 1).End(xlUp).Row
lastCol = DSheet.Cells(1, DSheet.Columns.Count).End(xlToLeft).Column
Notice here that you have to reference DSheet inside of the Cells reference to guarantee that you're referring to the same worksheet. Otherwise VBA could assume that you're referring to the ActiveSheet, which may be completely different and give you an incorrect value.
The next few lines become:
'Selects first to last filled row, and first to last filled column for data
Dim PRange As Range
Set PRange = DSheet.Cells(1, 1).Resize(lastRow, lastCol)
'Create pivot cache
Dim PCache As PivotCache
Set PCache = ActiveWorkbook.PivotCaches.Create _
(SourceType:=xlDatabase, SourceData:=PRange)
Your next statement in your code is Sheets("Tools").Activate which, unless there is a specific reason you want to display that worksheet to the user at this time, is completely unnecessary. If you want the user to view this worksheet when all processing is completed, move this statement to the end of the Sub.
Next:
'Create blank pivot table
Dim PTable As PivotTable
Set PTable = PCache.CreatePivotTable _
(TableDestination:=PSheet.Range("F1"), _
TableName:="ExcPT1")
The real fix for your error comes next:
'Create blank pivot chart
Dim PChart As Chart
Set PChart = PSheet.Shapes.AddChart
PChart.ChartType = xlPie
PChart.SetSourceData Source:=PSheet.Range("$F$2:$H$19"), PlotBy:=xlRows
Because you're creating an object for the newly added chart, you never have to use ActiveChart. It follows the same idea of specifying complete references.
And so on... you can hopefully use these examples to finish out the rest of your code and work through some of the issues you're having. Give it a try.

Related

Add and remove rows for bar chart created by VBA

I need to create Bar chart in Excel VBA. I used the code below, but when I am ADDING or DELETING A ROW it is not working.
I need that chart on fixed range (K1). Because when I am calculating for the second time it creates another chart.
How can I change the code to prevent a new chart being added when I adjust the data source?
Private Sub CommandButton2_Click()
Sheets("Sheet7").Range("F2:H12").Select
ActiveSheet.Shapes.AddChart.Select
ActiveChart.ChartType = xlBarClustered
ActiveChart.SetSourceData Source:=Range("Sheet7!$F$2:$H$12")
ActiveChart.SeriesCollection(1).Name = "=Sheet7!$G$1"
ActiveChart.SeriesCollection(2).Name = "=Sheet7!$H$1"
End Sub
In the sample code below it checks to see if a chart called TheChart already exists, and if not, creates a new one. You can now add and remove rows and the chart should will update. Additionally, if you add a new row at the bottom and click the button it will redraw TheChart without creating a new one.
The chart is always located at the top-left of K1 per the rngChartTopLeft variable - which you can adjust if required.
The code assumes that it is running in a Sheet module (hence Set ws = Me) and if you were running it in a standard module you can set the sheet with Set ws = ThisWorkbook.Worksheets("your_sheet").
Option Explicit
Private Sub CommandButton1_Click()
Dim ws As Worksheet
Dim chto As ChartObject
Dim rngChartTopLeft As Range
Dim rngData As Range
' assumes the code is in a sheet object
Set ws = Me
' top left of chart
Set rngChartTopLeft = ws.Range("K1")
' create chart or get existing chart
If ws.ChartObjects.Count = 0 Then
Set chto = ws.ChartObjects.Add( _
Left:=rngChartTopLeft.Left, _
Width:=500, _
Top:=rngChartTopLeft.Top, _
Height:=500)
chto.Name = "TheChart"
Else
Set chto = ws.ChartObjects("TheChart")
End If
' set chart type
chto.Chart.ChartType = xlBarClustered
' get data range per last row of data
Set rngData = ws.Range("F2:G" & ws.Cells(ws.Rows.Count, "G").End(xlUp).Row)
' set new chart range
chto.Chart.SetSourceData rngData
End Sub
please check the below code:
Option Explicit
Private Sub CommandButton1_Click()
Dim mychart As Shape
Dim lastrow As Long
lastrow = Sheet7.Cells(Rows.Count, "F").End(xlUp).Row
For Each mychart In ActiveSheet.Shapes
If mychart.Name = "CommandButton1" Then GoTo exit_
mychart.Delete
exit_:
Next
Sheets("Sheet7").Range("F2:H" & lastrow).Select
ActiveSheet.Shapes.AddChart.Select
ActiveChart.ChartType = xlBarClustered
ActiveChart.SetSourceData Source:=Range("Sheet7!$F$2:$H$" & lastrow)
ActiveChart.SeriesCollection(1).Name = "=Sheet7!$G$1"
ActiveChart.SeriesCollection(2).Name = "=Sheet7!$H$1"
End Sub

Run-Time Error 1004 - Macro to update pivot table

I am trying to update a pivot table using a macro since data is added to the bottom of the table each month (Update to include data to last row).
Option Explicit
Sub Pivot()
Dim shConD As Worksheet
Dim shPvtTbl As Worksheet
Dim lr As Long
Dim rng As Range
Set shConD = ActiveWorkbook.Sheets("Consolidated_Data")
Set shPvtTbl = ActiveWorkbook.Sheets("PivotTables")
lr = shConD.Range("A" & Rows.Count).End(xlUp).Row
Set rng = shConD.Range("A1:F" & lr)
With shPvtTbl.PivotTables(3).PivotCache
.SourceData = rng.Address(True, True, xlR1C1, True) 'Error appears here
.Refresh
End With
End Sub
On the .SourceData line, I am getting run-time error 1004, Application-defined or object-defined error. Followed logic from this thread and the continued chat . Thanks in advance guys.
If you're using Excel 2007 or later, then the simplest way to accomplish this is to make sure your PivotTable source data is an Excel Table (aka ListObject), and use the Table name in the Change PivotTable Data Source as shown below.
Thanks to the magic of Tables, from that point on, whenever you add new data to your Table, it will expand automatically. And whenever you refresh the PivotTable it will always pick up that new data automatically. There will be no need to change the PivotTable data source ever again.
Try the code below (explanation inside the code's comments) :
Option Explicit
Sub Pivot()
Dim shConD As Worksheet
Dim shPvtTbl As Worksheet
Dim lr As Long
Dim rng As Range
' Added PivotTable variables
Dim PvtTbl As PivotTable
Dim PvtCache As PivotCache
Set shConD = ActiveWorkbook.Sheets("Consolidated_Data")
Set shPvtTbl = ActiveWorkbook.Sheets("PivotTables")
lr = shConD.Range("A" & shConD.Rows.Count).End(xlUp).Row
Set rng = shConD.Range("A1:F" & lr)
' set/update the PivotCache (with latest rng modifications
Set PvtCache = ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:=rng.Address(False, False, xlA1, xlExternal))
' for DEBUG Only
Debug.Print PvtCache.SourceData
' set the PivotTable object
Set PvtTbl = shPvtTbl.PivotTables(3)
' for DEBUG Only
Debug.Print PvtTbl.Name
' refresh the PivotTable with the updated PivotCache
PvtTbl.ChangePivotCache PvtCache
PvtTbl.RefreshTable
End Sub

Run time error 1004 "Cannot open PivotTable source file"

I want to create a pivot table based on a dataset (contained in a worksheet) in the same workbook.
The workbook is open when I run the macro. The dataset comes from running a query in Access, and then export it to excel. I also tried to save the workbook prior to running the macro. I am using excel 2016.
This is my code:
Sub BusinessInteligenceCreatePivotTable()
Dim PivotSheet As Worksheet
Dim pvtCache As PivotCache
Dim pvt As PivotTable
'Determine the data range you want to pivot
Set pvtCache = ThisWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:=wsPartsMachines.Name & "'!" & wsPartsMachines.Range("A1").CurrentRegion.Address, Version:=xlPivotTableVersion15)
'Create a new worksheet
With ThisWorkbook
Set PivotSheet = .Sheets.Add(After:=.Sheets(.Sheets.Count))
PivotSheet.Name = "Production Schedule"
End With
PivotSheet.Activate
Range("A1").Select
'Create Pivot table from Pivot Cache
'Set pvt = pvtCache.CreatePivotTable(TableDestination:=ActiveCell, TableName:="ProductionSchedule")
Set pvt = PivotSheet.PivotTables.Add(PivotCache:=pvtCache, TableDestination:=ActiveCell, TableName:="ProdSched")
End Sub
The two last lines generates the same error message. "Run time error 1004. Cant open PivotTable source file 'C:\Users...'".
Does anybody know how to solve this problem?
Thanks.
EDIT
When I record a macro, VBA gives me this code (it works).
Sub BusinessInteligenceCreatePivotTable()
Dim PivotSheet As Worksheet
With ThisWorkbook
Set PivotSheet = .Sheets.Add(After:=.Sheets(.Sheets.Count))
PivotSheet.Name = "Production Schedule"
End With
PivotSheet.Activate
Range("A1").Select
ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:= _
"Parts & Machines2!R1C1:R1328C14", Version:=6).CreatePivotTable _
TableDestination:=ActiveCell, TableName:="PivotTable1", DefaultVersion:=6
End Sub
I want my SourceData's range to be dynamically set. My efforts to do it generates (with debug.print): 'Parts & Machines2'!R1C1:R1328C14
It seems to be different from the macro-recorded :"Parts & Machines2!R1C1:R1328C14".
Is it this difference that generates the error that i cant find the source data?
Screenshot of Data.
I am not so sure where you define wsPartsMachines as Worksheet and where you set it.
However, the error is in the line:
Set pvtCache = ThisWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:=wsPartsMachines.Name & "'!" & wsPartsMachines.Range("A1").CurrentRegion.Address, Version:=xlPivotTableVersion15)
If you add a line after:
Debug.Print pvtCache.SourceData
You will get 'Sheet3'''!R1C1:R6C3 in the immediate window - you have one ' too many. (I have used "Sheet3" as my SourceData)
Try to modify this line to :
Set pvtCache = ThisWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:=wsPartsMachines.Name & "!" & wsPartsMachines.Range("A1").CurrentRegion.Address)
Edit 1: Try a different approach, bring the data source direclty as Range:
Dim pvtDataRng As Range
Set wsPartsMachines = Sheets("Parts & Machines2")
' set the Pivot Table Data Source Range
Set pvtDataRng = wsPartsMachines.Range("A1").CurrentRegion
Set pvtCache = ThisWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:=pvtDataRng)
'Create Pivot table from Pivot Cache
Set pvt = PivotSheet.PivotTables.Add(PivotCache:=pvtCache, TableDestination:=ActiveCell, TableName:="ProdSched")
This code works. Still not sure why SourceData does not work. With small changes in the code that Shai Rado suggested it worked. Below is the code.
Sub BusinessInteligenceCreatePivotTable()
Dim PivotSheet As Worksheet
Dim pvtCache As PivotCache
Dim pvtTable As PivotTable
Dim ws1PartMachines As Worksheet
Dim pvtDataRng As Range
'Determine the data range you want to pivot
Set ws1PartsMachines = Worksheets("Parts & Machines2")
' set the Pivot Table Data Source Range
Set pvtDataRng = ws1PartsMachines.Range("A1").CurrentRegion
Set pvtCache = ThisWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:=pvtDataRng)
Debug.Print pvtCache.SourceData
'Create a new worksheet
With ThisWorkbook
Set PivotSheet = .Sheets.Add(After:=.Sheets(.Sheets.Count))
PivotSheet.Name = "Production Schedule2"
End With
PivotSheet.Activate
Range("A1").Select
'Create Pivot table from Pivot Cache
Set pvtTable = PivotSheet.PivotTables.Add(PivotCache:=pvtCache, TableDestination:=ActiveCell, TableName:="ProdSched")
End Sub

VBA run time error 91 Object variable or with block variable not set

Hi I am totally new to VBA. Currently I am learning how to use vba to create Pivottable and charts. But I am facing the Error 91 problem after debugged my code as below.
I am trying to count the number of failpartid occurred at certain time, and then draw the pivottable to show the count number. Thank you!
P.S: So I edited and checked my code again, but found out the "PT is nothing" during debugging. I have dim PT at the beginning, does anybody know why?
With .PivotFields("FailPartId") is the line has the error.
Sub Trial1()
Dim PTCache As PivotCaches
Dim PT As PivotTables
Dim PF As PivotFields
Dim FinalCol As Long
FinalCol = ActiveSheet.Cells(1, Columns.Count).End(xlToLeft).Column
'Range("E1:F1").Select
'Range(Selection, Selection.End(xlDown)).Select
Selection.Name = "PivotData"
Application.Goto Reference:="Trial1"
'Create the Cache
Set PTCaches = ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:="ActiveSheet!A1")
'Create the pivot table
Set PT = PTCaches.CreatePivotTable(TableDestination:=ActiveSheet.Cells(1, FinalCol + 2), TableName:=”PivotTable1”, ReadData:="PivotData")
'Set the Fields
With PT
'Set column field
With .PivotFields("FailPartId")
.Orientation = xlColumnField
.Position = 1
End With
'Set Row field
With .PivotFields("ProductionYM")
.Orientation = xlRowField
.Position = 1
End With
'Set data feild
ActiveSheet.AddDataField.PivotFields ("FailPartId"), "Count of FailPartId", xlCount
End With
End Sub
If you have put Option Explicit at the top and to Debug-->Compile VBAProject, you will solve it yourself.
Replace all PTCaches with PTCache and then change the line
Dim PTCache As PivotCaches to Dim PTCache As PivotCache.
Also the ” may become another issue. TableName:=”PivotTable1” is not the same as TableName:="PivotTable1"

I am trying to copy the sheet1 range data to sheet2 range but,nothing copied

I am trying to copy the sheet1 range data to sheet2 range but nothing gets copied. This is the full code which I was trying to achieve something but got stuck in the basic place. Please help
Edit: I tried the Macro just now and the same thing happened with this code. Please see the snapshot where you can see that Snap 1 contains source data and also selected but does not get copied to Snap 2. However the ranges are selected there.
Sub copy()
Range("A1:J4").Select
Selection.copy
Sheets("Sheet2").Select
ActiveSheet.Paste
Application.CutCopyMode = False
ActiveWorkbook.Save
End Sub
UpDate
Style-1
Option Explicit
Dim objSheet1,objSheet2,TotalRows,TotalcolCopy,strPathExcel1
Dim oXls : Set oXls = CreateObject("Excel.Application")
Dim aData ': aData = oWb.Worksheets(1).Range("$A2:$C10")
Dim dicP : Set dicP = CreateObject("Scripting.Dictionary")
strPathExcel1 = "D:\WIPData\AravoMacro\Finalscripts\GE_Wing_To_Wing_Report.xlsx"
oXls.Workbooks.open strPathExcel1
Set objSheet1 = oXls.ActiveWorkbook.Worksheets(1)
Set objSheet2 = oXls.ActiveWorkbook.Worksheets(2)
TotalRows=oXls.Application.WorksheetFunction.CountA(objSheet1.Columns(1)) - 3
TotalcolCopy=oXls.Application.WorksheetFunction.Match("Parent Business Process ID", objSheet1.Rows(3), 0)
objSheet1.Range(objSheet1.Cells(4,1),objSheet1.Cells(TotalRows,TotalcolCopy)).Copy(objSheet2.Range("A1"))
'=======================
oXls.ActiveWorkbook.SaveAs strPathExcel1
oXls.Workbooks.close
oXls.Application.Quit
'======================
Style-2
Option Explicit
Dim objSheet1,objSheet2,TotalRows,TotalcolCopy,strPathExcel1
Dim oFS : Set oFS = CreateObject("Scripting.FileSystemObject")
Dim oXls : Set oXls = CreateObject("Excel.Application")
Dim aData ': aData = oWb.Worksheets(1).Range("$A2:$C10")
Dim dicP : Set dicP = CreateObject("Scripting.Dictionary")
oXls.Workbooks.Open(oFs.GetAbsolutePathName("Test.xlsx"))
Set objSheet1 = oXls.ActiveWorkbook.Worksheets(1)
Set objSheet2 = oXls.ActiveWorkbook.Worksheets(2)
TotalRows=oXls.Application.WorksheetFunction.CountA(objSheet1.Columns(1)) - 3
TotalcolCopy=oXls.Application.WorksheetFunction.Match("Parent Business Process ID", objSheet1.Rows(3), 0)
objSheet1.Range(objSheet1.Cells(4,1),objSheet1.Cells(TotalRows,TotalcolCopy)).Copy(objSheet2.Range("A1"))
'=======================
oXls.ActiveWorkbook.SaveAs "Test.xlsx"
oXls.Workbooks.close
oXls.Application.Quit
'======================
Could you people tell me what differences between Style-1 and Style-2.Because in Style-1 all the copied data get saved,which is not the case in Style-2. This design issue mainly the overall problem i was facing from morning.
In what way Style-2 is not perfect?
The simplest way to copy from one range to another would be to recoding macro. Looking at your code, what are the values you are getting for TotalRows and LastCol? Assuming you have matching data returned from your Match(), so there're rows to copy`
Option Explicit
Sub CopyPastes()
Dim rng1 as Range
Dim rng2 as Range
Set rng1 = Sheets(1).Range("B2:C12")
Set rng2 = Sheets(2).Range("B2")
rng1.Copy
rng2.PasteSpecial xlPasteValues
End Sub
So in your case, can you keep it simple? Remove the following line. Just specify the starting Range of the Sheet2 and try out. You do not have to worry about resize at this point.
replace this,
ObSheet2.Range(ObSheet2.Cells(4,1),ObSheet2.Cells(TotalRows,LastCol)).PasteSpecial
with either: coz you are missing paste special argument
ObSheet2.Range(ObSheet2.Cells(4,1),ObSheet2.Cells(TotalRows,LastCol)) _
.PasteSpecial xlPasteValues
or : here without any fancy cells, but direct range
ObSheet2.Range(ObSheet2.Range("A4").PasteSpecial xlPasteValues