To Use Shape.DrawSpline Method (Visio) from MS Access VBA - vba

I was reading up on the use of Shape.DrawSpline Method (Visio) from MS office VBA reference. The example they gave works when I entered it within Visio. The example takes points and connect them with a curve and display it in the Visio application.
I wish to have the VBA code reside within MS Access and I will have VBA code open a Visio drawing, and execute the Shape.DrawSpline Method from MS Access VBA code. My problem seems to determine how to generate the expression shape to get the program to run and draw the sample curve in the open Visio drawing.
Here is the code I was working on, and the part that opens up a Visio drawing is working for me:
Dim AppVisio As Visio.Application
Dim ShpObj As Visio.Shape
Dim XYPoints(70) As Double
Set AppVisio = CreateObject("Visio.Application")
Set DocObj = AppVisio.Documents.Open("C:\Test Template.vsd")
When I command MS Access to execute the above code, the Visio Drawing "Test Template.vsd" does open it.
Immediately following the above code, I have the x, y coordinates of the points to be ploted. They are assigned to the XYPoints array.
At the bottom, I have the following code which was used to execute the DrawSpline Method (Visio) from MS Access VBA code.
Here is that code:
Set ShpObj = AppVisio.Application.ActivePage.DrawSpline(XYPoints, 0.25, visSplinePeriodic)
I get an error in the above statement. Here is the error I get:
"Run-time error '-2032465751 (86db08a9)'
Method 'DrawSpline' of object 'IVPage' failed
Thank You,

I agrree with #y4cine's advice. However my guess is either your document isn't opening correctly, or your populating of your points array isn't in the correct format. The following adaptation of the SDK sample works for me:
Sub TestSplineFromExcel()
Dim vApp As Visio.Application
Set vApp = CreateObject("Visio.Application")
Dim intCounter As Integer
Dim XYPoints(1 To (5 * 2)) As Double
For intCounter = 1 To 5
'Set x components (array elements 1,3,5,7,9) to 1,2,3,4,5
XYPoints((intCounter * 2) - 1) = intCounter
'Set y components (array elements 2,4,6,8,10) to f(i)
XYPoints(intCounter * 2) = (intCounter * intCounter) - (7 * intCounter) + 15
Next intCounter
vApp.Documents.Add ""
Dim vPag As Visio.Page
Set vPag = vApp.ActivePage
If vPag Is Nothing Then
MsgBox "Target page is null"
Else
Dim shp As Visio.Shape
Set shp = vPag.DrawSpline(XYPoints, 0.25, Visio.VisDrawSplineFlags.visSplinePeriodic)
End If
End Sub

Related

Points property of ShapeNode fails in MS Word

The Code below implements the example presented in the Microsoft ShapeNode.Points property (Word) article:
Sub Test()
Dim PointsArray
Dim myDocument As Document
Dim currXvalue As Single
Dim currYvalue As Single
Set myDocument = ActiveDocument
With myDocument.Shapes(3).Nodes
PointsArray = .Item(2).Points
currXvalue = PointsArray(1, 1)
currYvalue = PointsArray(1, 2)
.SetPosition 2, currXvalue + 200, currYvalue + 300
End With
End Sub
Execution of the line 3 generates the RTE 13 (Type Mismatch). According to the Watch panel,
the type of the Points property is the array of Single (which is
correct)
the type of the myDocument.Shapes(3).Nodes.Item(2).Points
expression is Integer
See the screenshot below:
Verified on MS Word 2007. A problem of this kind exists for Word 2010. However, it was verified that the problem does not exist for MS PowerPoint 2007 and MS Excel 2007.
Seems to be an error in the Word object model. Can you please suggest a workaround?

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.

Code stopped working in Powerpoint 2016

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!

ActiveWindow VBA commands to access active slide does not work on PowerPoint 2013 running on virtual machine

I just started using VBA a few days ago. I noticed that some few commands do not seem to work on my computer and I was wondering whether this is due to my computer setup.
I am using VBA in PowerPoint 2013 on Windows 7 run via VMware Fusion (virtual machine) on MacOSX. I need to create a dynamic reference to the active slide, but several way of doing so broke my code:
Set oSl = Application.ActiveWindow.View.Slide
(as suggested here)
Set oSl = ActivePresentation.Slides(ActiveWindow.View.Slide.SlideNumber)
(as suggested here)
Set oSl = ActiveWindow.Selection.SlideRange.SlideIndex
(as suggested here)
None of these worked for me. Since I just started using VBA I simply inserted Message Boxes after different parts of the code, and looked at when the boxes where no longer triggered - in this case always after the "oSl =" line that I replaced with the various other approaches delineated above. Additionally,
Set oSl = ActiveWindow.Selection.SlideRange(1)
also broke my code (as discussed here)
What DID work so far was
Set oSl = ActivePresentation.SlideS(1)
All the methods above that didn't work (but should) contain "ActiveWindow". It would be great if you could advise on whether there are errors in my approach to selecting the active slide or whether the issue might be that VBA can't access the "ActiveWindow" properly because my PowerPoint runs on a virtual machine. Should that be the case, is there another way to select the currently active slide without using ActiveWindow?
EDIT: I am trying to apply this to the following code in PowerPoint. Basically what I want to do is replace the line "oSl = ActivePresentation.SlideS(1)" with a line of code that won't always target slide 1 but whichever slide is currently active. My question is not so much HOW to do this - there are plenty of instructions on how to do it online. My question is WHY these approaches are not working for me.
Sub SelectionMacro()
Dim oSl As Slide
Dim oSh As Shape
Dim aArrayOfShapes() As Variant
Dim ShapeX As Shape
Dim N As Long
Dim Temp As Variant
Dim J As Long
Dim FadeEffect As Effect
Set oSl = ActivePresentation.SlideS(1)
'This section creates an array of all pictures on Slide1 called
'"aArrayOfShapes"
For Each oSh In oSl.Shapes
If oSh.Type = msoPicture Then
On Error Resume Next
Debug.Print UBound(aArrayOfShapes)
If Err.Number = 0 Then
ReDim Preserve aArrayOfShapes(1 To UBound(aArrayOfShapes) + 1)
Else
ReDim Preserve aArrayOfShapes(1 To 1)
End If
Set aArrayOfShapes(UBound(aArrayOfShapes)) = oSh
End If
Next
'This section creates a random index number within the bounds of the
'length of aArrayOfShapes and assigns the shape with that index number
'to the Shape object ShapeX
Randomize
NumberX = Int((UBound(aArrayOfShapes) - (LBound(aArrayOfShapes) - 1)) * Rnd) + LBound(aArrayOfShapes)
Set ShapeX = aArrayOfShapes(NumberX)
'This section shuffles aArrayOfShapes
For N = LBound(aArrayOfShapes) To UBound(aArrayOfShapes)
J = CLng(((UBound(aArrayOfShapes) - N) * Rnd) + N)
If N <> J Then
Set Temp = aArrayOfShapes(N)
Set aArrayOfShapes(N) = aArrayOfShapes(J)
Set aArrayOfShapes(J) = Temp
End If
Next N
'This section loops through all Shapes in aArrayOfShapes and
'fades them out one by one EXCEPT for ShapeX
For Each Shape In aArrayOfShapes
If ShapeX.Name <> Shape.Name Then
Set FadeEffect = oSl.TimeLine.MainSequence.AddEffect _
(Shape:=Shape, effectid:=msoAnimEffectFade, trigger:=msoAnimTriggerAfterPrevious)
With FadeEffect
.Timing.Duration = 0.5
.Exit = msoTrue
End With
End If
Next Shape
End Sub
I had similar problem.
Try to replace:
ActiveWindow.View.Slide.SlideNumber
with:
ActivePresentation.SlideShowWindow.View.Slide.SlideIndex
It was what I needed in my project, maybe it helps you.

Making a macro to generate a custom show in Powerpoint

I want to make a macro for PowerPoint, to generate a custom show, containing all the slides from my PowerPoint but in random order.
How would I do this?
I want to be able to run it and create different custom shows each time.
It's been 3 years since I used PowerPoint, and the only experience I have with VB was a little bit of VB6 in 2004.
Check out the info here.
Sample:
Sub sort_rand()
Dim i As Integer
Dim myvalue As Integer
Dim islides As Integer
islides = ActivePresentation.Slides.Count
For i = 1 To ActivePresentation.Slides.Count
myvalue = Int((i * Rnd) + 1)
ActiveWindow.ViewType = ppViewSlideSorter
ActivePresentation.Slides(myvalue).Select
ActiveWindow.Selection.Cut
ActivePresentation.Slides(islides - 1).Select
ActiveWindow.View.Paste
Next
End Sub