I am trying to create a chart and reposition it afterwards to the correct location on my PowerPoint sheet. But receive a runtime error. The relevant bits of code are:
(My chart data is not in the code)
Dim myChart As chart
Dim gChartData As ChartData
Dim gWorkBook As Excel.Workbook
Dim gWorkSheet As Excel.Worksheet
'Create the chart and set a reference to the chart data.
Set myChart = ActivePresentation.Slides(2).Shapes.AddChart.chart
Set gChartData = myChart.ChartData
'Set the Workbook and Worksheet references.
Set gWorkBook = gChartData.Workbook
Set gWorkSheet = gWorkBook.Worksheets(1)
With myChart
.ChartType = xlColumnStacked
.ChartStyle = 30
.ApplyLayout 4
.ClearToMatchStyle
End With
With myChart
.PlotArea.Left = 290
.PlotArea.Top = 90
End With
I receive the following error code:
Error: -2147467259 (80004005) during Runtime:
Method Left of object PlotArea failed
Some searching already suggested I may have a macro security problem but in the options all macro actions are currently allowed.
If you need further information please let me know.
Your code is moving the chart within the shape that it's been added to, rather than moving the container shape itself.
You need to move the parent of myChart:
Sub Test()
Dim myChart As Chart
Set myChart = ActivePresentation.Slides(2).Shapes.AddChart.Chart
With myChart
.ChartType = xlColumnStacked
.ChartStyle = 30
.ApplyLayout 4
.ClearToMatchStyle
'Move shape containing chart on PPT.
With .Parent
.Left = 290
.Top = 90
End With
'Move chart plot area within chart (I think).
.PlotArea.Left = 290
.PlotArea.Top = 90
End With
End Sub
I didn't get the error you have, but that could be trying to move the PlotArea outside the shape?
Related
how to set chart location i have below code
Dim rng As Range
Dim cht As Object
'Your data range for the chart
Set rng = ActiveSheet.Range("C10:Q12")
'Create a chart
Set cht = ActiveSheet.Shapes.AddChart2
'Give chart some data
cht.Chart.SetSourceData Source:=rng
'Determine the chart type
cht.Chart.ChartType = xlLineMarkers
'Change chart's title
cht.Chart.ChartTitle.Text = "Budget vs Actual (Income)"
You mean, location of chart on the worksheet?
First, you're better off using this to declarecht:
Dim cht As ChartObject
Then to locate cht, you can use (for example):
cht.Left = 150
cht.Top = 100
or tie cht to a cell's location:
cht.Left = ActiveSheet.Range("D4").Left
cht.Top = ActiveSheet.Range("D4").Top
Sub OO()
Dim oPPApp As Object, oPPPrsn As Object, oPPSlide As Object
Dim oPPShape As Object
Dim FlName As String
'~~> Change this to the relevant file
FlName = "C:\Users\lich_\Documents\test.pptx"
'~~> Establish an PowerPoint application object
On Error Resume Next
Set oPPApp = GetObject(, "PowerPoint.Application")
If Err.Number <> 0 Then
Set oPPApp = CreateObject("PowerPoint.Application")
End If
Err.Clear
On Error GoTo 0
oPPApp.Visible = True
Set oPPPrsn = oPPApp.Presentations.Open(FlName, WithWindow:=msoFalse)
Set oPPSlide = oPPPrsn.Slides(2)
With oPPSlide.Shapes("Chart1").Chart.ChartData
.ActivateChartDataWindow
.Workbook.Worksheets("Sheet1").Range("B2").Value = 0.1231
.Workbook.Close
End With
End Sub
As you can see above, I'm trying to edit the chart data in vba.
But since I have control many charts later, I would like to make the workbook invisible ( or not open it at all if possible )
With oPPSlide.Shapes("Chart1").Chart.ChartData
.ActivateChartDataWindow
.Workbook.Worksheets("Sheet1").Range("B2").Value = 0.1231
.Workbook.Close
End With
In this code I opened by "ActivateChartDataWindow" method and change the data which I want and Closed.
Is there any way to make the window invisible or to edit data without even opening?
Thank you for your help in advance.
It's possible to update existing chart data without Activate as per #mooseman's answer.
However, if the chart is new/inserted at runtime, as far as I know this cannot be accomplished with interop, as the AddChart method adds the chart and simultaneously creates/activates the Excel Workbook. While you may not need to call the Activate method, there is no way to insert or add a new chart that doesn't involve opening an Excel instance. There is no way around this, this is just how the UI functions and it is by design.
To Update Data in EXISTING Chart / ChartData
Below native PowerPoint VBA, but should port easily to Excel with proper reference(s)
Sub test()
Dim PPT As PowerPoint.Application
Dim pres As Presentation
Dim sld As Slide
Dim shp As Shape
Dim cht As Chart
Dim rng As Object ' Excel.Range
Set PPT = Application 'GetObject(,"PowerPoint.Application")
Set pres = ActivePresentation
Set sld = pres.Slides(1)
Set shp = sld.Shapes(1)
Set cht = shp.Chart
Call changeData(cht, 6.3)
pres.Slides.AddSlide pres.Slides.Count + 1, sld.CustomLayout
Set sld = pres.Slides(pres.Slides.Count)
sld.Shapes.AddChart().Chart.ChartData.Workbook.Application.WindowState = -4140
Set cht = sld.Shapes(1).Chart
Call changeData(cht, 3.9)
End Sub
Sub changeData(c As Chart, v As Double)
Dim rng As Object
With c.ChartData
Set rng = .Workbook.Worksheets(1).ListObjects(1).Range
rng.Cells(2, 2).Value = v ' etc.
.Workbook.Close
End With
End Sub
The requirement is to use the With block in VBA.
Some brief tests suggest this is also doable via Interop from python using win32com:
from win32com import client
ppt = client.Dispatch("PowerPoint.Application")
pres = ppt.ActivePresentation
sld = pres.Slides[0]
cht = sld.Shapes[0].Chart
cht.ChartData.Workbook.Worksheets[0].ListObjects[0].Range.Cells(2,2).Value = 9
And also in C#:
using Microsoft.Office.Interop.PowerPoint;
public static void foo(int value = 10)
{
Application ppt = new Microsoft.Office.Interop.PowerPoint.Application();
Presentation pres = ppt.ActivePresentation;
Slide sld = pres.Slides[1];
Chart cht = sld.Shapes[1].Chart;
{
cht.ChartData
.Workbook.Worksheets[1].ListObjects[1].Range.Cells(2, 2).Value = value;
}
}
To Minimize the ChartData / Workbook Window:
In practice I have not had reliable luck using the With method. If you cannot get it to work, then the next-best option is to minimize the window immediately:
Sub changeData(c As Chart, v As Double)
Dim rng As Object
With c.ChartData
.Activate
.Workbook.Application.WindowState = -4140 '## Minimize Excel
'## DO STUFF:
Set rng = .Workbook.Worksheets(1).ListObjects(1).Range
rng.Cells(2, 2).Value = v ' etc.
.Workbook.Close
End With
End Sub
Note that this method does briefly flash Excel on the screen, and this sucks because in that brief instant, it can intercept keystrokes/etc.
You don't have to activate the chartdata worksheet to make changes to it.
With oPPSlide.Shapes("Chart1").Chart.ChartData
'this updates the value in the datasheet
.Workbook.Sheets(1).Range("B2").Value = 0.1231
End with
You can also set the chartdata sheet to equal a range in an excel sheet
path2 = "C:\JohnDoe\Vasquez_061118.xlsm"
Set xlWorkBook = Workbooks.Open(FileName:=path2, ReadOnly:=True)
With oPPSlide.Shapes("Chart1").Chart.ChartData
'this updates the value in the datasheet
.Workbook.Sheets(1).Range("A1:B2").Value = xlWorkBook.Sheets(1).Range("A2:B3").Value
End With
Sub OO()
Dim oPPApp As Object, oPPPrsn As Object, oPPSlide As Object
Dim oPPShape As Object
Dim FlName As String
'~~> Change this to the relevant file
FlName = "C:\Users\lich_\Documents\test.pptx"
'~~> Establish an PowerPoint application object
On Error Resume Next
Set oPPApp = GetObject(, "PowerPoint.Application")
If Err.Number <> 0 Then
Set oPPApp = CreateObject("PowerPoint.Application")
End If
Err.Clear
On Error GoTo 0
oPPApp.Visible = True
Set oPPPrsn = oPPApp.Presentations.Open(FlName, WithWindow:=msoFalse)
Set oPPSlide = oPPPrsn.Slides(2)
With oPPSlide.Shapes("Chart1").Chart.ChartData
.ActivateChartDataWindow
.Workbook.Worksheets("Sheet1").Range("B2").Value = 0.1231
.Workbook.Close
End With
End Sub
As you can see above, I'm trying to edit the chart data in vba.
But since I have control many charts later, I would like to make the workbook invisible ( or not open it at all if possible )
With oPPSlide.Shapes("Chart1").Chart.ChartData
.ActivateChartDataWindow
.Workbook.Worksheets("Sheet1").Range("B2").Value = 0.1231
.Workbook.Close
End With
In this code I opened by "ActivateChartDataWindow" method and change the data which I want and Closed.
Is there any way to make the window invisible or to edit data without even opening?
Thank you for your help in advance.
It's possible to update existing chart data without Activate as per #mooseman's answer.
However, if the chart is new/inserted at runtime, as far as I know this cannot be accomplished with interop, as the AddChart method adds the chart and simultaneously creates/activates the Excel Workbook. While you may not need to call the Activate method, there is no way to insert or add a new chart that doesn't involve opening an Excel instance. There is no way around this, this is just how the UI functions and it is by design.
To Update Data in EXISTING Chart / ChartData
Below native PowerPoint VBA, but should port easily to Excel with proper reference(s)
Sub test()
Dim PPT As PowerPoint.Application
Dim pres As Presentation
Dim sld As Slide
Dim shp As Shape
Dim cht As Chart
Dim rng As Object ' Excel.Range
Set PPT = Application 'GetObject(,"PowerPoint.Application")
Set pres = ActivePresentation
Set sld = pres.Slides(1)
Set shp = sld.Shapes(1)
Set cht = shp.Chart
Call changeData(cht, 6.3)
pres.Slides.AddSlide pres.Slides.Count + 1, sld.CustomLayout
Set sld = pres.Slides(pres.Slides.Count)
sld.Shapes.AddChart().Chart.ChartData.Workbook.Application.WindowState = -4140
Set cht = sld.Shapes(1).Chart
Call changeData(cht, 3.9)
End Sub
Sub changeData(c As Chart, v As Double)
Dim rng As Object
With c.ChartData
Set rng = .Workbook.Worksheets(1).ListObjects(1).Range
rng.Cells(2, 2).Value = v ' etc.
.Workbook.Close
End With
End Sub
The requirement is to use the With block in VBA.
Some brief tests suggest this is also doable via Interop from python using win32com:
from win32com import client
ppt = client.Dispatch("PowerPoint.Application")
pres = ppt.ActivePresentation
sld = pres.Slides[0]
cht = sld.Shapes[0].Chart
cht.ChartData.Workbook.Worksheets[0].ListObjects[0].Range.Cells(2,2).Value = 9
And also in C#:
using Microsoft.Office.Interop.PowerPoint;
public static void foo(int value = 10)
{
Application ppt = new Microsoft.Office.Interop.PowerPoint.Application();
Presentation pres = ppt.ActivePresentation;
Slide sld = pres.Slides[1];
Chart cht = sld.Shapes[1].Chart;
{
cht.ChartData
.Workbook.Worksheets[1].ListObjects[1].Range.Cells(2, 2).Value = value;
}
}
To Minimize the ChartData / Workbook Window:
In practice I have not had reliable luck using the With method. If you cannot get it to work, then the next-best option is to minimize the window immediately:
Sub changeData(c As Chart, v As Double)
Dim rng As Object
With c.ChartData
.Activate
.Workbook.Application.WindowState = -4140 '## Minimize Excel
'## DO STUFF:
Set rng = .Workbook.Worksheets(1).ListObjects(1).Range
rng.Cells(2, 2).Value = v ' etc.
.Workbook.Close
End With
End Sub
Note that this method does briefly flash Excel on the screen, and this sucks because in that brief instant, it can intercept keystrokes/etc.
You don't have to activate the chartdata worksheet to make changes to it.
With oPPSlide.Shapes("Chart1").Chart.ChartData
'this updates the value in the datasheet
.Workbook.Sheets(1).Range("B2").Value = 0.1231
End with
You can also set the chartdata sheet to equal a range in an excel sheet
path2 = "C:\JohnDoe\Vasquez_061118.xlsm"
Set xlWorkBook = Workbooks.Open(FileName:=path2, ReadOnly:=True)
With oPPSlide.Shapes("Chart1").Chart.ChartData
'this updates the value in the datasheet
.Workbook.Sheets(1).Range("A1:B2").Value = xlWorkBook.Sheets(1).Range("A2:B3").Value
End With
I'm trying to generate two charts using VBA. The problem is most examples use ActiveChart but I want multiple charts on multiple sheets. If I inserted a blank chart how do I rename that chart to reference it. I don't want a new chart to be generated each time I run the macro and I want it to be in the sheet. I'm struggling with the code but am assuming it will be something like the code below. I've attached the desired graph (I made this through excel, but I need to do it through VBA).
macro1()
lastrow2 = Sheet1.Cells(Sheet1.Rows.Count, "A").End(xlUp).Row
dim chart1 as chart
dim chart2 as chart ' ect
chart1.title = "test"
chart1.xaxis = sheet1.cell(lastrow2,1)
chart1.yaxis = "manhours"
end sub
using a the record function, i got the code commented below. I tried to change it but i'm still having issues
Sub Macro7()
Dim Chart2 As ChartObject
Dim chartb As Chart
Chart2 = Sheet1.chartb.SeriesCollection(2)
chartb.Select
Formula = "=SERIES(Master!R3C3,Master!R4C1:R18C1,Master!R4C3:R19C3,2)"
' ActiveChart.SeriesCollection(2).Select
' Selection.Formula =_
'"=SERIES(Master!R3C3,Master!R4C1:R18C1,Master!R4C3:R19C3,2)"
End Sub
I really just need this formula converted to i can reference my lastrow function and individual sheets
ActiveChart.SeriesCollection(2).Select
Selection.Formula =_
"SERIES(sheet1.cells(3,3),sheet1.cells(4,1):sheet1.cells(18,1)_
,sheet1.cells(4,3):sheet1.cells(4,19),2"
' Selection.Formula"_
' =SERIES(Master!R3C3,Master!R4C1:R18C1,Master!R4C3:R19C3,2)"
this was what i was trying to do. It declares the sheet name and references an existing chart named chart 1.
Dim cht As ChartObject
Dim rng As Range
Set cht = Sheets("Master").ChartObjects("Chart 1")
Set rng = Sheets("Master").Range("A4", Range("D4").End(xlDown).Offset(-1))
cht.Chart.SetSourceData Source:=rng
cht.Chart.HasTitle = True
cht.Chart.ChartTitle.Text = "Bird Report - By Cost Code/Activity" ' title
cht.Chart.SeriesCollection(1).Name = "=Master!$B$3"
cht.Chart.SeriesCollection(2).Name = "=Master!$C$3"
cht.Chart.SeriesCollection(3).Name = "=Master!$D$3"
I am running a macro to resize my plot area to make all graphs uniform within a report. However, when resizing the plot area the Chart Data Table resizes as well and the Labels for the rows in the Data Table become text wrapped. This issue is fixed if I manually resize the Plot Area slightly and then the text is fixed and is autofit and no longer text wrapped to take up three or four lines. Any way to fix this? This is my current code.
Sub Color_Loop_Series()
Dim sht As Worksheet
Dim CurrentSheet As Worksheet
Dim cht As ChartObject
Dim ser As Series
For Each sht In ActiveWorkbook.Worksheets
For Each cht In sht.ChartObjects
cht.Activate
ActiveChart.ChartType = xlLineMarkers
ActiveChart.Legend.Position = xlLegendPositionBottom
ActiveChart.Legend.Font.Size = 9
ActiveChart.PlotArea.Select
Selection.Width = 380
Selection.Left = 11
Selection.Top = 3
Selection.Height = 250
ActiveChart.Axes(xlValue).AxisTitle.Position = xlAxisPositionLeft
ActiveChart.DataTable.Font.Size = 5.5
Next cht
Next sht
End Sub
I was able to duplicate your problem using Excel 2010 by recording a macro while moving the plot area. When running the recorded macro the data table legend resized and text wrapped. I was not able to find any direct handle for the data table legend but did find that both .Left and .InsideLeft affect word wrapping.
Here is your code, modified a little to remove all Active statements.
Sub Color_Loop_Series()
Dim sht As Worksheet
Dim CurrentSheet As Worksheet
Dim cht As ChartObject
Dim ser As Series
For Each sht In ActiveWorkbook.Worksheets
For Each cht In sht.ChartObjects
With cht.Chart
.ChartType = xlLineMarkers
.Legend.Position = xlLegendPositionBottom
.Legend.Font.Size = 9
.DataTable.Font.Size = 5.5
.Axes(xlValue).AxisTitle.Position = xlAxisPositionLeft
End With
With cht.Chart.PlotArea
.Width = 380
.Height = 250
.Left = 11
.Top = 3
.InsideLeft = 80 '<- Adjust this value
End With
Next cht
Next sht
End Sub
Results when using .InsideLeft
Results when not using .InsideLeft