Visio: change format of multiple selected shapes - vba

I'm trying to create a macro I can call with a right-click to change shape line weight and line color. The shapes are custom shapes that I've created in stencil. I was able to do it successfully to a single shape with this code but it doesn't work when multiple shapes are selected:
Sub Macro1()
Dim vsoShape As Visio.Shape
Set vsoShape = Visio.ActiveWindow.Selection.shapeID.Item(1)
vsoShape.CellsSRC(visSectionObject, visRowLine, visLineColor).FormulaU = "THEMEGUARD(RGB(255,0,0))"
vsoShape.CellsSRC(visSectionObject, visRowLine, visLineWeight).FormulaU = "2.25 pt"
End Sub
I tried iterating through the selected shapes, but haven't found a working way to do it. This was my most recent attempt.
Sub Macro1()
Dim shapeID As Long
Dim vsoShape As Visio.Shape
Dim vsoSel As Visio.Selection
Dim intCounter As Integer
Set vsoSel = Visio.ActiveWindow.Selection
Call vsoSel.GetIDs(shapeIDs)
For intCounter = LBound(shapeIDs) To UBound(shapeIDs)
shapeID = shapeIDs(intCounter)
Set vsoShape = Visio.ActiveWindow.Selection.shapeID.Item(1)
vsoShape.CellsSRC(visSectionObject, visRowLine, visLineColor).FormulaU = "THEMEGUARD(RGB(255,0,0))"
vsoShape.CellsSRC(visSectionObject, visRowLine, visLineWeight).FormulaU = "2.25 pt"
ActiveWindow.Select vsoSel
Next
End Sub

Well done on your code so far, however there's a couple of issues with your example:
shapeID isn't a property of Selection
Item takes an index (in a collection) rather than an ID (use ItemFromID for that)
You need to declared the array: Dim shapeIDs() As Long
To set the window selection at the end you need to use the Window.Selection property
Having said all of that the Selection object is a collection that you can for each over directly.
For example:
Public Sub Iterate1()
Dim vShp As Visio.Shape
Dim vSel As Visio.Selection
Set vSel = Visio.ActiveWindow.Selection
For Each vShp In vSel
vShp.CellsSRC(visSectionObject, visRowLine, visLineColor).FormulaU = "THEMEGUARD(RGB(255,0,0))"
vShp.CellsSRC(visSectionObject, visRowLine, visLineWeight).FormulaU = "2.25 pt"
Next
End Sub
And as alternative to the SRC syntax you can also use cell name sytax which is often easier to read:
vShp.CellsU("LineColor").FormulaU = "THEMEGUARD(RGB(255,0,0))"
vShp.CellsU("LineWeight").FormulaU = "2.25 pt"

Related

Unlock with macro when read-only in PowerPoint

I want to remove read-only using a PowerPoint macro.
I'm writing a macro that fires when a file is opened.
In that macro, there is a process to delete a specific shape.
The PowerPoint file has a write lock.
Given the above assumptions, when you open the file read-only
The macro will be executed, but an error will occur because it is read-only and the shape cannot be deleted.
So I unlock the read-only lock when the macro is executed
When I'm done deleting a particular shape, I want to lock it again for read-only.
Is there such a way?
I know the write lock password.
Public Sub Ribbon_onLoad(ribbon As IRibbonUI)
Const EXP_DATE As Date = "2021/09/30"
Dim NOW_DATE As Date: NOW_DATE = Format(Date, "yyyy/mm/dd")
Dim pp As PowerPoint.Presentation: Set pp = ActivePresentation
If NOW_DATE <= EXP_DATE Then
MsgBox "OK!"
Call DeleteShapesWithName("expShape")
Else
MsgBox "No!Exp!:" + Format(EXP_DATE, "yyyy/mm/dd")
'ActivePresentation.Close
End If
End Sub
Sub DeleteShapesWithName(ByVal targetName As String)
Dim sld As Slide
Dim shp As Shape
Dim i As Long
i = 1
For Each sld In Application.ActivePresentation.Slides
Do Until i > sld.Shapes.Count
If sld.Shapes(i).Name = targetName Then
sld.Shapes(i).Delete
Else
i = i + 1
End If
Loop
Next
End Sub
------add
I added the modified source after receiving the reply.
Public Sub Ribbon_onLoad(ribbon As IRibbonUI)
Call UnlockPresentation
End Sub
Sub UnlockPresentation()
Dim oPVW As ProtectedViewWindow
Dim oPres As Presentation
Set oPVW = ProtectedViewWindows.Open("C:\test\example_exp.pptm")
oPVW.Edit ModifyPassword:="test"
Call DeleteShapesWithName("expShape")
'Do stuff here
End Sub
Sub DeleteShapesWithName(ByVal targetName As String)
Dim sld As Slide
Dim shp As Shape
Dim i As Long
i = 1
For Each sld In Application.ActivePresentation.Slides
Do Until i > sld.Shapes.Count
If sld.Shapes(i).Name = targetName Then
sld.Shapes(i).Delete
Else
i = i + 1
End If
Loop
Next
End Sub
Here's code to open a read-only presentation so you can modify it. No need to reset the password, just replace "Test" with the actual password. Where the Do stuff here comment is, you can use the ActivePresentation keyword to modify the file:
Sub UnlockPresentation()
Dim oPVW As ProtectedViewWindow
Dim oPres As Presentation
Set oPVW = ProtectedViewWindows.Open("C:\HasModPW.pptx")
oPVW.Edit ModifyPassword:="ExistingModificationPassword"
'Do stuff here
End Sub
Please note: Microsoft's help page on ProtectViewWindow.Edit is wrong. The page currently states this method changes the password, but it actually provides the PW to make editing possible,

Catia: 2D Points to 3D Points

I have a Catia part where I have a few sketches on different planes. I need to be able to convert these sketches into 3D points which I copy to a new part document.
I have tried to use the Search and Selection commands in VB script in order to use a macro to pick up all the 2D points in my sketch and convert them to 3D points but to no avail.
Sub CATMain()
Set oSel = CATIA.ActiveDocument.Selection
strArray(0)=”Part”
Msgbox “Please select parts to join.”
sStatus = oSel.SelectElement3(strArray, “Select parts”, False, CATMultiSelTriggWhenUserValidatesSelection, false)
iCount = oSel.Count
For i= 1 to iCount
Set myObject2 = oSel.Item(i).value
oSel.Search “Name=Point,sel”
ReDim copies(iCount)
For k=1 to iCount
Set copies(k)=oSel.Item(k).Value
oSel.Add copies(k)
oSel.Copy
Next ‘k
Next ‘i
Set part2 = CATIA.Documents.Add(“CATPart”)
part2.Product.PartNumber = “My New Part”
Dim GSet1 As HybridBody
Set GSet1 = part2.Part.HybridBodies.Item(1)
GSet1.Name = “My Geometry”
Set partDocument2= CATIA.ActiveDocument
Dim ActSel As Selection
Set ActSel=partDocument2.Selection
ActSel.Add GSet1
ActSel.PasteSpecial(“CATPrtResultWithOutLink” )
ActSel.Clear
End Sub
You have to disassemble the sketch to get at the points as something you can copy
The disassemble command is exposed in VB via the HybridShapeFactory.AddNewDatums method.
Option Explicit
Sub CATMain()
Dim oPart As part
Set oPart = CATIA.ActiveDocument.part
Dim oHSF As HybridShapeFactory
Set oHSF = oPart.HybridShapeFactory
Dim sx As Sketch
Set sx = oPart.HybridBodies.item("Geometrical Set.1").HybridSketches.item("Sketch.1")
'make a temporary body
Dim targetGS As HybridBody
Set targetGS = oPart.HybridBodies.add
targetGS.name = "TMP_BODY___DELETE_ME"
'create a datum curve from the sketch
Dim sxRef As Reference
Set sxRef = oPart.CreateReferenceFromObject(sx)
'make a zero-translate from the sketch
'This is required because AddNewDatums functions needs a HybridShape feature
Dim oZero As HybridShapeTranslate
Set oZero = oHSF.AddNewTranslate(sxRef, oHSF.AddNewDirectionByCoord(0#, 0#, 1#), 0#)
Call targetGS.AppendHybridShape(oZero)
Call oPart.UpdateObject(oZero)
'now do the disassembly
Dim oZeroRef As Reference
Set oZeroRef = oPart.CreateReferenceFromObject(oZero)
'un-datum the curve by making a zero translate
Dim domains() As Variant
domains = oHSF.AddNewDatums(oZeroRef)
Dim i As Integer
For i = 0 To UBound(domains)
Call targetGS.AppendHybridShape(domains(i))
Next
Call oPart.Update
'now we can copy the resulting points...
Dim oSel As Selection
Set oSel = CATIA.ActiveDocument.Selection
Call oSel.add(targetGS)
Call oSel.Search("'Generative Shape Design'.Point,sel")
'copy paste into the new part
MsgBox ("There are " & oSel.count & " points ready to copy")
< YOUR COPY PASTE CODE GOES HERE>
'delete the temporary geo set
Call oHSF.DeleteObjectForDatum(oPart.CreateReferenceFromObject(targetGS))
End Sub

How to add layers to a selection in Visio 2007 VBA?

I want to export certain layers to svg through VBA in Visio 2007.
I am getting stuck on adding the layers to the selection. How do I do this?
Sub tester()
Dim Layer As Visio.Layer
Dim Layers As Visio.Layers
Dim sel As Visio.Selection
Dim filename As String
Dim lyrName As String
Dim iLays As Integer
Set Layers = Application.ActivePage.Layers
Set sel = EmptySelection 'Or whatever empty initialization neeeds to happen...
For iLays = 1 To Layers.Count
Set Layer = Layers(iLays)
lyrName = Layer.Name
If lyrName = "Walls" Or lyrName = "Zones" Then
sel.AddLayer (lyrName) 'or some such nonsense - This is broked.
End If
filename = Application.ActiveDocument.Path & "PootyStuff.svg"
'Export the page as svg file
sel.Export filename
Next iLays
Set Layer = Nothing
Set Layers = Nothing
End Sub
Try this code
Sub tester()
Dim sel As Visio.Selection
Dim filename As String
ActiveWindow.DeselectAll
' create selection by layers
Set sel = ActivePage.CreateSelection(visSelTypeByLayer, visSelModeSkipSuper, "Walls;Zones")
filename = Application.ActiveDocument.Path & "PootyStuff.svg"
'Export the page as svg file
sel.Export filename
End Sub

Macro in LibreOffice to change the background of an Impress Slide to a solid black color

Looked all around and could not find it. Need a macro so that I can repeat it 695 times, on 695 different files I have. Documentation is kind of uneasy, or I am unlucky.
I could do it in Microsoft VBA as follows:
Sub VbaBlackies
Dim oSl As Slide
For Each oSl In ActivePresentation.Slides
With oSl
.FollowMasterBackground = msoFalse
.DisplayMasterShapes = msoFalse
With .background
.Fill.ForeColor.RGB = RGB(0, 0, 0)
.Fill.BackColor.RGB = RGB(0, 0, 0)
End With
End With
Next oSl
End Sub
I am looking for something similar in LibreOffice BASIC. I could get started in the code this way:
Sub Main
Dim oDoc As Object
Dim oDPages As Object
Dim oDPage As Object
oDoc= ThisComponent
oDPages = oDoc.getDrawPAges()
For i=0 To oDPages.count()-1
oDPage = oDPages.getByIndex(i)
oDPage.Background = RGB(0,0,0) 'This does not work.
'I have no idea on how to access the object's properties and alter them.
Next i
End Sub
Any ideas, please?
What you are looking for is in Listing 15.1 of Andrew Pitonyak's macro document, an essential reference for macro programming.
Sub ChangeBackground
Dim oDoc as Object
oDoc = ThisComponent
Dim oDrawPages as Object, oDrawPage as Object
oDrawPages = oDoc.getDrawPages()
oDrawPage = oDrawPages.getByIndex(0)
Dim oBackground as Object
oBackground = oDoc.createInstance("com.sun.star.drawing.Background")
oBackground.FillColor = RGB(250,0,0)
oDrawPage.Background = oBackground
End Sub
API documentation is at https://www.openoffice.org/api/docs/common/ref/com/sun/star/drawing/Background.html.
YES! Worked like a charm, thanks a lot for the answers!
This is the final code that worked out for me:
Sub Main
Dim oDoc As Object
Dim oDPages As Object
Dim oDPage As Object
oDoc = ThisComponent
oDPages = oDoc.getDrawPAges()
For i=0 To oDPages.count()-1
oDPage = oDPages.getByIndex(i)
Dim oBackground As Object
oBackground = oDoc.createInstance("com.sun.star.drawing.Background")
oBackground.FillColor = RGB(0,0,0)
oDPage.Background = oBackground
Next i
End Sub

Unable to iterate the CustomerData collection (Invalid Procedure Call error)

I am attempting to store xml metadata within chart shapes in a PowerPoint presentation.
I need to ensure that the shape only contains the current xml data, so I have a function to delete existing data (if any) and add the current data.
Sub Test()
Dim cht as Chart
Dim xml as String
Set cht = ActivePresentation.Slides(1).Shapes(1)
xml = "<Chart property1='true' property2='false'>blah blah blah</Chart>"
EmbedChartXML xml, cht
End Sub
Sub EmbedChartXML(xml As String, cht As Shape)
Dim x As Variant
'Get rid of any previous data
For Each x In cht.CustomerData
x.Delete
Next
Set xmlPart = cht.CustomerData.Add
xmlPart.LoadXML xml
End Sub
The For Each loop is failing with the indicated error message. I can see that the cht.CustomerData.Count = 2 (for example), but if I try to view this in the Locals window, I get the same error.
UPDATE
Here is another test routine that is failing, even though there is nothing inside the For/Next loop.
Sub TestIteration()
Dim sld As Slide
Dim pres As Presentation
Dim shp As Shape
Dim x As CustomXMLPart
Set pres = ActivePresentation
Set sld = pres.Slides(2)
For Each shp In sld.Shapes
Set pptCustomerData = shp.CustomerData
For Each x In shp.CustomerData
' For Each pptCustomXMLPart In pptCustomerData
' Debug.Print pptCustomXMLPart.Id
' Next
Next
Next
End Sub
Others here cannot replicate this error in Excel 2013 (I am using Excel 2010) where the collection object itself becomes inaccessible. Perhaps there is a bug or something, but I could not find much on Google about similar errors...
I ultimately arrive at this solution. I am not sure why the CustomXMLPart's .Delete method doesn't actually delete the item from the collection (instead it makes it to Nothing, and then failure on successive iteration attempts).
Instead, I use the CustomerData.Delete method. This seems to be working as expected.
Sub EmbedChartXML(xml As String, cht As Shape)
Dim x As Variant
Dim cData As CustomerData
Dim xID As String
Set cData = cht.CustomerData
Debug.Print cht.CustomerData.Count
'Get rid of any previous data
For Each x In cData
xID = x.Id
cData.Delete xID
Next
With cData.Add
.LoadXML xml
End With
Debug.Print cht.CustomerData.Count
End Sub