Selecting Shapes

J

John Sheppard

Excuse me if this question has been answered, but I've looked and if
there is an answer, I'm not finding it.

I'm trying to use VBA in Visio to access shapes on a page. It looks
like I have to define both a collection of shapes and an individual
shape object. As I use these objects in my code, it looks like I have
to set my individual shape object with a reference to the index of a
shape in the collection of shapes. So far, I'm okay with this,
however...

It looks like the only way to create all the shape objects in the
collection is to either start by selecting them before running the
macro OR creating them as part of the code, as is shown in this
example...

'This Microsoft Visual Basic for Applications (VBA) macro
'demonstrates selecting, deselecting, and subselecting shapes.

Public Sub Select_Example ()

Const MAX_SHAPES = 6
ReDim shpObjs(1 To MAX_SHAPES) As Visio.Shape

Dim i As Integer
Dim shpObj As Visio.Shape

'Draw some shapes.
For i = 1 To MAX_SHAPES
Set shpObjs(i) = ActivePage.DrawRectangle(i, i + 1, i + 1, i)
Next i

ActiveWindow.DeselectAll

For i = 1 To 3
ActiveWindow.Select shpObjs(i), visSelect
Next i

<snip>

I don't want to do either one of these. I what I want is to be able to
reference the shapes by their ID number.

I want to be able to say that shpObj = activePage.item(shapeID)...or
something like that. I just can't figure out if that's possible, and
if so how you do it.

Any help is much appreciated. Thanks!
 
M

Michael J. Hunter [MS]

John,

As you've learned, the Page, Master, and Shape objects each have collection
of their children shapes. You can attach to a specific shape by providing
its index in the collection, its name, or its unique ID. The code samples
all create and/or select the shapes directly in the code so that you can
cut-and-paste it and have it run without needing to do anything else, but
you can certainly work with shapes that are already created before running
the macro. For example, this macro opens an existing drawing and iterates
over every shape on the active page:

Public Sub PrintAllShapeNames()
Dim openedDocument As Visio.Document
Set openedDocument = Documents.Open("c:\temp\MyDrawing.vdx")

Dim currentShape As Visio.Shape
For Each currentShape In ActivePage.Shapes
Debug.Print currentShape.NameU
Next currentShape

openedDocument.Close
End Sub

You can go directly to a specific shape as well. This macro sets the
foreground fill of a specific shape to be red:

Public Sub MakeShapeRed(ByVal shapeName As String)
' If the shape does not exist Visio will throw an error, so we turn off
error handling so we can
' handle that eventuality ourself.
On Error Resume Next

Dim shapeToModify As Visio.Shape
Set shapeToModify = ActivePage.Shapes(shapeName)
If (Not shapeToModify Is Nothing) Then
shapeToModify.CellsSRC(visSectionObject, visRowFill,
visFillForegnd).FormulaU = 2
End If
End Sub

Developing Microsoft Visio Solutions has more details about using the Item
property at
http://msdn.microsoft.com/library/d...en-us/devref/HTML2/DAR_Properties_(I)_785.asp.


Michael J. Hunter
Microsoft
michhu-at-online-dot-microsoft-dot-com

Developing Microsoft Visio Solutions:
http://msdn.microsoft.com/library/en-us/devref/HTML/DVS_Copyright_1270.asp
Developer Resources for Microsoft Visio:
http://msdn.microsoft.com/library/default.asp?url=/nhp/Default.asp?contentid=28000456

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm
 
R

Reinier Post

Michael said:
[,..] For example, this macro opens an existing drawing and iterates
over every shape on the active page:

Public Sub PrintAllShapeNames()
Dim openedDocument As Visio.Document
Set openedDocument = Documents.Open("c:\temp\MyDrawing.vdx")

Dim currentShape As Visio.Shape
For Each currentShape In ActivePage.Shapes
Debug.Print currentShape.NameU
Next currentShape

openedDocument.Close
End Sub

One remark: at least in Visio 2000, this only returns the top level shapes,
not the shapes within groups. Visio doesn't appear to offer a direct way
to iterate over *all* shapes on a given page; however, if you already
know their IDs,

ActivePage.Shapes.Item(theID)

*will* return the shape on the ActivePage with the shape.ID "theID",
even if it is nested and therefore not returned in the For loop.

Of course you can always iterate recursively:

Private Sub PrintAllShapeNamesIn(theShapes as Visio.Shapes)

Dim currentShape As Visio.Shape

For Each currentShape In ActivePage.Shapes
Debug.Print currentShape.NameU
If currentShape.Type = Visio.visTypeGroup then
PrintAllShapeNamesIn currentShape.Members
End If
Next currentShape

End Sub

Public Sub PrintAllShapesOnActivePage()

PrintAllShapeNamesIn ActivePage.Shapes

End Sub
 
R

Reinier Post

Michael said:
[,..] For example, this macro opens an existing drawing and iterates
over every shape on the active page:

Public Sub PrintAllShapeNames()
Dim openedDocument As Visio.Document
Set openedDocument = Documents.Open("c:\temp\MyDrawing.vdx")

Dim currentShape As Visio.Shape
For Each currentShape In ActivePage.Shapes
Debug.Print currentShape.NameU
Next currentShape

openedDocument.Close
End Sub

One remark: at least in Visio 2000, this only returns the top level shapes,
not the shapes within groups. Visio doesn't appear to offer a direct way
to iterate over *all* shapes on a given page; however, if you already
know their IDs,

ActivePage.Shapes.Item(theID)

*will* return the shape on the ActivePage with the shape.ID "theID",
even if it is nested and therefore not returned in the For loop.

Of course you can always iterate recursively:

Private Sub PrintAllShapeNamesIn(theShapes As Visio.Shapes)

Dim currentShape As Visio.shape

For Each currentShape In theShapes
Debug.Print currentShape.nameu
If currentShape.Type = Visio.visTypeGroup Then
PrintAllShapeNamesIn currentShape.Shapes
End If
Next

End Sub

Public Sub PrintAllShapesOnActivePage()

PrintAllShapeNamesIn ActivePage.Shapes

End Sub
 
R

Reinier Post

Reinier Post wrote:

[a posting with errors,
and it looks as though the server won't let me cancel it]
[,..] For example, this macro opens an existing drawing and iterates
over every shape on the active page:

Public Sub PrintAllShapeNames()
Dim openedDocument As Visio.Document
Set openedDocument = Documents.Open("c:\temp\MyDrawing.vdx")

Dim currentShape As Visio.Shape
For Each currentShape In ActivePage.Shapes
Debug.Print currentShape.NameU
Next currentShape

openedDocument.Close
End Sub

One remark: at least in Visio 2000, this only returns the top level shapes,
not the shapes within groups. Visio doesn't appear to offer a direct way
to iterate over *all* shapes on a given page; however, if you already
know their IDs,

ActivePage.Shapes.Item(theID)

*will* return the shape on the ActivePage with the shape.ID "theID",
even if it is nested and therefore not returned in the For loop.

Of course you can always iterate recursively:

(My posting had code here that wouldn't even compile. Improved:)

Private Sub PrintAllShapeNamesIn(theShapes As Visio.Shapes)

Dim currentShape As Visio.shape

For Each currentShape In theShapes
Debug.Print currentShape.nameu
If currentShape.Type = Visio.visTypeGroup Then
PrintAllShapeNamesIn currentShape.Shapes
End If
Next

End Sub

Public Sub PrintAllShapesOnActivePage()

PrintAllShapeNamesIn ActivePage.Shapes

End Sub
 
M

Michael J. Hunter [MS]

You are correct: recursing into a shape's shapes is the only way to iterate
over sub-shapes.


Michael J. Hunter
Microsoft
michhu-at-online-dot-microsoft-dot-com

Developing Microsoft Visio Solutions:
http://msdn.microsoft.com/library/en-us/devref/HTML/DVS_Copyright_1270.asp
Developer Resources for Microsoft Visio:
http://msdn.microsoft.com/library/default.asp?url=/nhp/Default.asp?contentid=28000456

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top