Code stopped working in Powerpoint 2016 - vba

Code that perfectly works in earlier versions of PPT stopped working in 2016.
When I try to change the left property of a shape in a chart, I get a Method left of object shape failed error.
I can perfectly read the .Left property.
I am running out of ideas? What can I do?
Sub test11()
Dim sld As Slide
Dim objChart As Object
Dim shpBubble As Object
Set sld = ActivePresentation.Slides("ScatterPlot01_Purch6")
Set objChart = sld.Shapes("Chart01").Chart
sld.Select
objChart.Select
Set shpBubble = objChart.Shapes("P01")
'shpBubble.Select
Debug.Print shpBubble.Left, shpBubble.Visible
shpBubble.Left = 10
End Sub

UPDATE
Having tested in PowerPoint 2010 and 2013, where it works, this now looks like a bug in 2016!
* END *
I managed to recreate the error in PowerPoint 2016 (PC) by manually adding a shape to a test chart (select the chart then click Format / Insert Shapes) and trying to write to several of it's properties including position and formatting such as changing fill colour. All generate an error.
Maybe one workaround is to use the .Delete method to delete the desired shape and then add a new shape at the required size and position. Something like this:
Sub test11()
Dim sld As Slide
Dim objChart As Chart 'Object
Dim shpBubble As Shape 'Object
Set sld = ActivePresentation.Slides("ScatterPlot01_Purch6")
Set objChart = sld.Shapes("Chart01").Chart
sld.Select
objChart.Select ' this won't work as you can only select the parent shape sld.Shapes("Chart01")
With objChart
.Shapes("P01").Delete
.Shapes.AddShape msoShapeOval, 10, 10, 20, 20
End With
End Sub
The challenge is that because the new shape is added as read only, the formatting can't be set!

Related

VB.NET - Programatically close the chart data object

My program is automating PowerPoint to loop through a series of chart parameters and create a new chart per parameter set. So far it works well for the first chart - however, it throws an error when attempting to create a second chart because the chart data grid is already open, and I can't find a method to properly close or dispose of the data grid after generating the graph.
Abridged code:
Imports Powerpoint = Microsoft.Office.Interop.PowerPoint
Imports Excel = Microsoft.Office.Interop.Excel
Private Sub generatePowerPoint(Qnum As String)
Try
'Create PowerPoint object and assign a presentation / slide to it
Dim oApp As Powerpoint.Application
Dim oPres As Powerpoint.Presentation
Dim oSlide As Powerpoint.Slide
oApp = New Powerpoint.Application()
oApp.Visible = True
oApp.WindowState = Powerpoint.PpWindowState.ppWindowMinimized
oPres = oApp.Presentations.Add
'Prepare to generate charts based on parameters in a listbox
Dim slideCount = lbQuestions.Items.Count
For slideN = 1 To slideCount
'Add a blank slide per graph request
oSlide = oPres.Slides.Add(slideN, Powerpoint.PpSlideLayout.ppLayoutBlank)
'Create a new shape object for each slide
Dim chartShape(slideCount) As Powerpoint.Shape
' What's causing the error: assign a chart object to the next shape object.
' This works for the first slide, but then throws an error that the PowerPoint
'Chart Data Grid is still open, preventing it from creating a new chart.
chartShape(slideN - 1) = oSlide.Shapes.AddChart2(-1, ChartFind(chartType), 50, 50, 775, 410)
Dim cData = chartShape(slideN - 1).Chart.ChartData 'Activate to refresh
Dim workbook = cData.Workbook
workbook.Application.Visible = False
Dim datasheet = workbook.Worksheets(1)
Dim colNumber As Integer = 2
Dim firstRowNumber As Integer = 2
datasheet.rows.clear()
datasheet.columns.clear()
For r = categoryNames.Count - 1 To 0 Step -1
datasheet.Cells(r + firstRowNumber, 1) = categoryNames(r)
Next
... Code to assign data and format the chart object ...
'Refresh the range accepted by the chart object
chartShape(slideN-1).Chart.Refresh
'Loop again
Next
I've spent some time going through the PowerPoint Interop docs and the PowerPoint Chart Object Model docs on msdn (e.g. https://learn.microsoft.com/en-us/previous-versions/office/developer/office-2010/ff760412(v=office.14), https://msdn.microsoft.com/en-us/vba/powerpoint-vba/articles/chartdata-object-powerpoint), and it seems that there's while there's a method to call the Chart Data Grid (chartdata.activate()) , there isn't a method to close the Chart Data Grid.
The exact error message thrown is "System.Runtime.InteropServices.COMException (0xBFFF64AA): The chart data grid is already open in 'Presentation 1 - PowerPoint'. To edit the data for this chart, you need to close it first. at Microsoft.Office.Interop.PowerPoint.Shapes.AddChart2( ..."
Does anyone have a suggestion?
Solved, mostly. For those who may have the same issue:
chartShape.Chart.ChartData.Workbook.close()
This is an undocumented method / IntelliSense will not provide it (hence the capitalization on Close), but after opening a chart object and editing the data, make sure you finish the code block with this before attempting to create a new chart object.
Now, this doesn't work if the open workbook isn't the one you opened (so for example, I can't test if there is a workbook opened by the user, and if so, close it). I'm resolving this issue by encapsulating the AddChart2 method in a Try Catch method, and if an error is thrown I let the user know to close the window and exit the subroutine so the program doesn't crash.

Change the text color of the chart title in a PowerPoint Histogram chart

I am trying to change the text color of the chart title of a histogram chart in PowerPoint.
Here is what I do:
var colorFormat = chart.ChartTitle.Format.TextFrame2.TextRange.Font.Fill.ForeColor;
colorFormat.RGB = ...;
// or
colorFormat.ObjectThemeColor = ...;
This works for the standard charts like line charts. But it doesn't work for other chart types like histogram, waterfall, tree map etc.
In these cases, setting ObjectThemeColor sets the text to black. Setting RGB does actually set the correct color. However, in both cases, as soon as the user changes the selection, the text color jumps back to the one it had previously.
How can I set the text color of the title of one of these charts?
I am using VSTO and C# but a VBA solution is just as welcome as long as it can be translated to C# and still work.
Based on what info you gave I built a histogram and waterfall chart in PowerPoint and was successful using:
Sub ChartTitleFontColor()
Dim oShp As Shape
Dim oCht As Chart
'Waterfall on slide 1
Set oShp = ActivePresentation.Slides(1).Shapes(1)
If oShp.HasChart Then
Set oCht = oShp.Chart
End If
' Do stuff with your chart
If oCht.HasTitle Then
Debug.Print oCht.ChartTitle.Text
oCht.ChartTitle.Format.TextFrame2.TextRange.Font.Fill.ForeColor.RGB = RGB(251, 5, 40)
End If
'Histogram on slide 2
Set oShp = ActivePresentation.Slides(2).Shapes(1)
If oShp.HasChart Then
Set oCht = oShp.Chart
End If
' Do stuff with your chart
If oCht.HasTitle Then Debug.Print oCht.ChartTitle.Text
oCht.ChartTitle.Format.TextFrame2.TextRange.Font.Fill.ForeColor.RGB = RGB(251, 5, 40)
End If
' Clean up
Set oShp = Nothing
Set oCht = Nothing
End Sub
Your code works in my test. I created two charts in PowerPoint 2016, the first one a waterfall, and the second another type. The following code changes the title color only (and text just a proof of it being changed) and nothing else. I can select the other chart and nothing changes. I could not find a bug about this in a search. Perhaps something in the remaining code is changing it back?
Sub test()
Dim myPresentation As Presentation
Set myPresentation = ActivePresentation
Dim myShape As Shape
Set myShape = myPresentation.Slides(1).Shapes(1)
Dim theChart As Chart
If myShape.HasChart Then
Set theChart = myShape.Chart
If theChart.ChartTitle.Text = "This is blue" Then
theChart.ChartTitle.Text = "This is yellow"
theChart.ChartTitle.Format.TextFrame2.TextRange.Font.Fill.ForeColor.RGB = RGB(255, 255, 0)
Else
theChart.ChartTitle.Text = "This is blue"
theChart.ChartTitle.Format.TextFrame2.TextRange.Font.Fill.ForeColor.RGB = RGB(0, 255, 255)
End If
End If
End Sub
This is not exactly an answer but I think you should name your object.
Instead of using
ActivePresentation.Slides(1).Shapes(1)
You can name the object.

VBA Chart automation using ActivateChartDataWindow

I'm building a chart automation script in powerpoint and i have any issue when calling upon "ActivateChartDataWindow".
I would use "Activate" instead of "ActivateChartDataWindow", but "Activate" loads the full Excel program and makes the whole routine run slow and ulgy.
The problem I have is that "ActivateChartDataWindow" does work to populate the charts, but when I manually go to edit the data - right click, edit data - to access the excel application, it does not seem to want to load!
It has been driving my crazy for the last 5 hours and would appreciate any ideas on how to over come this.
OLE.dlll are working correctly and the code I am using is given below.
Code below:
There are 5 slides with one chart on each page and the code below is what i am using as a point of concept
I have a felling i am using "ActivateChartDataWindow" wrong, but there is not much on the web to know what i am doing wrong! Arrrhhhh!
For i = 1 To 5
Set instance = Nothing
Set instance = ActivePresentation.Slides(i).Shapes(1).Chart.ChartData
With instance
.ActivateChartDataWindow
instance.Workbook.Sheets(1).Range("A1:H26").Value = 27
instance.Workbook.Close
End With
Next i
End Sub
As always recommended, you don't need to Activate an object to modify it. If you're trying to handle a Workbook embedded in a slide, you can do it this way
' This function will get you a Workbook object embedded in a Slide (late binding)
Function getEmbeddedWorkbook(sld As Slide) As Object
Dim shp As Shape
On Error Resume Next
For Each shp In sld.Shapes
If shp.Type = 3 Then ' embedded chart workbook created in PP
Set getEmbeddedWorkbook = shp.Chart.ChartData.Workbook
Exit Function
End If
If shp.Type = 7 Then ' embedded workbook pasted from excel
Set getEmbeddedWorkbook = shp.OLEFormat.Object
Exit Function
End If
Next
End Function
' For Testing, I have 6 slides, Some have a workbook pasted from Excel
' OLE, shape type = 7, others have a chart created in PP (type = 3)
Sub Test()
Dim wb As Object, i As Long
For i = 6 To 6 'ActivePresentation.Slides.Count
Set wb = getEmbeddedWorkbook(ActivePresentation.Slides(i))
If Not wb Is Nothing Then
wb.Sheets(1).Range("A1:D5").Value = i * i
End If
Next
End Sub

Referencing Charts By Name Only in PowerPoint VBA

I have been searching for hours to try to find the answer to this question, but to no avail, so I'm hoping I can find the answer here.
I want to create a variable that refers to a pre-existing chart in PowerPoint so I can start automating its data. I want to refer to the chart by its name to make things very easy, but no matter what I do I cannot seem to give PPT a satisfactory Chart address.
I have tried almost every possible variation of the below, but without success:
Dim chrtPP As PowerPoint.Chart
Set chrtPP = ActivePresentation.Slides(1).Shapes.Charts("Chart3")
Could someone please tell me what I'm doing wrong?
Thanks!
You need to reference the shape by name (a 'Shape" in PowerPoint is actually any object that is on a slide and can be a simple shape, textbox, table, chart, group, media clip etc.). If you're on PowerPoint 2010 and higher, press Alt+F10 to open the selection pane to find the name of the selected chart object. It may be a standard chart object or a chart within a placeholder object. You can then reference the chart as follows:
Option Explicit
Sub ChartStuff()
Dim oShp As Shape
Dim oCht As Chart
Set oShp = ActivePresentation.Slides(1).Shapes("Chart 3")
If oShp.HasChart Then
Set oCht = oShp.Chart
End If
' Do stuff with your chart
If oCht.HasTitle Then Debug.Print oCht.ChartTitle.Text
' Clean up
Set oShp = Nothing
Set oCht = Nothing
End Sub
The key in programming PowerPoint is to ignore the object name in the Object Model for 'Shape' as it's very misleading!

Crop an Image (Enhanced Metafile) in PPT 2007

Can anyone help me with an issue in PPT 2007.
I have an image (a chart from excel pasted as 'Picture (Enhanced Metafile)') in a slide. I just need to crop this image to fit in the slide. I tried following code, but to no avail:
'1:
With ActivePresentation.Slides(1).Shapes(1)
.PictureFormat.CropLeft = 10
.PictureFormat.CropTop = 10
.PictureFormat.CropRight = 10
.PictureFormat.CropBottom = 10
End With
'Runtime error "ActiveX Component can't create object
'2:
ActiveWindow.Selection.ShapeRange.PictureFormat.CropRight = 10
ActiveWindow.Selection.ShapeRange.PictureFormat.CropLeft = 10
ActiveWindow.Selection.ShapeRange.PictureFormat.CropBottom = 10
ActiveWindow.Selection.ShapeRange.PictureFormat.CropTop = 10
'Object doesnt support this property or method
Any suggestion is most welcome.
This works with EMFs pasted from Excel:
Dim oSh as Shape
Set oSh = ActiveWindow.Selection.ShapeRange(1)
' Note: ShapeRange(1), not just ShapeRange
' That's the problem with your second example
With oSh
.CropLeft = 10
' etc
End With
The fact that it's yelling about an activex object in the first example makes me wonder whether the first shape is really an EMF, which would not be an ActiveX object.