Update : I have received a corrected response from my friends at Microsoft regarding the use of Spatial Neighbors and Containers, so I have to revise this post from its original. The changes are marked in Red.
The Structured Diagramming API in Visio 2010 is really neat, but there are a couple of problems that I think you should be aware of. The first one is about how shapes can appear to be in a container, but aren’t really; and the second is how the Container type prevents SpatialNeighbors from working … unless you use a new constant.
Let’s start with an example diagram that contains three Process shapes on a Cross Functional Flowchart. Notice that I have select the Process shape labelled A and this has caused the swimlane Function 2 to display a brown highlight … this is a good indication that the Structured Diagramming
API is working, and that Function 2 is a container shape. I have placed two more Process shapes below the swimlanes, and one of them (C) is on top of a SubProcess shape.
Now, I wrote a short VBA function to list each Process shape along with the containers that each one thinks that it is within.
Public Sub UsingStructuredDiagram()
Dim shp As Visio.Shape
Dim aryIDs() As Long
Dim i As Integer
For Each shp In Visio.ActivePage.Shapes
If Not shp.Master Is Nothing Then
If shp.Master.Name = "Process" Then
Debug.Print shp.Text
aryIDs = shp.MemberOfContainers
For i = 0 To UBound(aryIDs)
Debug.Print , shp.ContainingPage.Shapes.ItemFromID(aryIDs(i)).Name, _
shp.ContainingPage.Shapes.ItemFromID(aryIDs(i)).Text
Next i
End If
End If
Next
End Sub
Running this function shows that Process A is within three containers … this is what I would expect because the swimlane is within a swimlane list, and there is always a phase separator.
A
Swimlane List
Swimlane Function 2
Separator Phase
B
D
I also wrote a short VBA function to do a similar list, but using the legacy SpatialNeighbors function.
Public Sub UsingSpatialNeighbors()
Dim sel As Visio.Selection
Dim shp As Visio.Shape
Dim shpIn As Visio.Shape
Dim aryIDs() As Long
Dim i As Integer
For Each shp In Visio.ActivePage.Shapes
If Not shp.Master Is Nothing Then
If shp.Master.Name = "Process" Then
Debug.Print shp.Text
Set sel = shp.SpatialNeighbors( _
visSpatialContainedIn, 0.001, _
visSpatialIncludeHidden)
For Each shpIn In sel
Debug.Print , shpIn.Name, shpIn.Text
Next shpIn
End If
End If
Next
End Sub
This time, only Process D is listed as being inside a container … the Subprocess C shape.
A
B
D
Subprocess C
Immediately, you can see that SpatialNeighbors method is not working for the swimlane, swimlane list and separator. This is the first problem.
Now, stretched the bottom edge of Function 2 so that it covers shapes B, C and D.
Notice that I have got shape B selected, but there is no tell-tale brown outline around Function 2. This is an indication that there is something amiss … This is the second problem. Sure enough, when I ran the UsingStructuredDiagram() function, the listing was unchanged:
A
Swimlane List
Swimlane Function 2
Separator Phase
B
D
Similarly, the UsingSpatialNeighbors() function produces an unchanged listing:
A
B
D
Subprocess C
Then I selected the three shapes and just wiggled them a little … and suddenly the tell-tale brown outline appeared:
Now when I ran the UsingStructuredDiagram() function, all three of the Process shapes recognised that they are inside the swimlane, etc.
A
Swimlane List
Swimlane Function 2
Separator Phase
B
Swimlane List
Swimlane Function 2
Separator Phase
D
Swimlane List
Swimlane Function 2
Separator Phase
But the UsingSpatialNeighbors() function still lists the same:
A
B
D
Subprocess C
UNLESS you add the visSpatialIncludeContainerShapes constant:
Public Sub UsingSpatialNeighbors() Dim sel As Visio.Selection Dim shp As Visio.Shape Dim shpIn As Visio.Shape Dim aryIDs() As Long Dim i As Integer For Each shp In Visio.ActivePage.Shapes If Not shp.Master Is Nothing Then If shp.Master.Name = "Process" Then Debug.Print shp.Text Set sel = shp.SpatialNeighbors( _ visSpatialContainedIn, 0.001, _ visSpatialIncludeHidden + visSpatialIncludeContainerShapes) For Each shpIn In sel Debug.Print , shpIn.Name, shpIn.Text Next shpIn End If End If Next End Sub
A
CFF Container Title
Swimlane Function 2
Swimlane List
B
CFF Container Title
Swimlane Function 2
Swimlane List
D
CFF Container Title
Swimlane Function 2
Swimlane List
Subprocess C
As a footnote, I opened the ShapeSheet of Function 2 shape, and removed the value “Container” in the User.msvStructureType cell.
This will, of course, stop the swimlane behaving correctly as far as the Structured Diagram is concerned, but it does allow the SpatialNeighbors() method to work, without the visSpatialIncludeContainerShapes constant, as can be seen by this output from the UsingSpatialNeighbors() function:
A
Swimlane Function 2
B
Swimlane Function 2
D
Swimlane Function 2
Subprocess C
I have made Microsoft aware of these problems, but until there is a fix, I hope this article helps you work around them … and now that I have had an updated response, I feel a little silly!
Paul Herber says
Another container problem here:
http://social.technet.microsoft.com/Forums/en-US/visiogeneral/thread/6063b6e2-ee85-4a38-b38a-5c544bfcce7e
davidjpp says
Paul,
It looks like you have identified a third problem with containers that we need to work around until there is a fix.
Tish says
It would be very helpfull for me, if you could briefly explain what all categories theese are:
– User.msvShapeCategories: CFF Container; Pool, (NameU: CFF Container)
– User.msvShapeCategories: CFF List; DoNotContain, (NameU: SwimLaneList)
– User.msvShapeCategories: Swimlane;Lane;DoNotContain, (NameU: Pool/Lane)
– User.msvShapeCategories: CFF List; DoNotContain (NameU: PhaseList)
– User.msvShapeCategories: Phase;DoNotContain , (NameU: Separator)
davidjpp says
Check out : http://blogs.msdn.com/b/visio/archive/2010/01/12/custom-containers-lists-and-callouts-in-visio-2010.aspx
Michael says
I’m sorry to ask this here, but I’ve searched the Web for several days and cannot find an answer to my question…
I’m using the latest version of Visio Professional (2019?) with the BPMN stencil. I hate the way Visio automatically encapsulates two pool/lane objects into a pool object. I’ve created my own BPMN stencil with a custom pool object and lane object. Each pool and lane object has custom formatting and captures shape data specific to the concept each is supposed to represent (pool is a process, lane is an actor in the process).
I need to turn off the Visio behavior that automatically wraps two BPMN container shapes dropped onto each other into a third encapsulating container (a pool). If I drop a lane onto a pool, I want to nest that lane w/in the pool, not have them become two lanes nested inside a new pool object that has none of the customizations I created in my stencil’s pool object and lane object.
I’ve played around with my pool object’s shapesheet and some of the properties and/or methods I’ve read about. I’ve managed to prevent pools from being nested within each other, which is a behavior I want, but it only works if I make the shapesheet updates after I drop the pool object on the page. It doesn’t work when I make the updates to the master shape on my stencil, but I can’t nest lanes in them, a behavior I don’t want, either.
I’m not a programmer and I know enough about shapesheets to be really dangerous (to myself). I just want to know if I can turn off Visio’s default BPMN container nesting behavior and nest those objects the way I want. I also want to be able to create multiple levels of nested lanes, which Visio also will not let you do.
Thanks for any help and insight.
David Parker says
There are two issues here, I think.
When you drag and drop a master, such as Pool/Lane, from a stencil, such as BPMN Basic Shapes, for the first time in a document, then Visio will automatically copy that master to the Document Stencil before creating a shape instance of the master where you drop it. From then on, each time you drag and drop the master from the stencil to anywhere in the document, then Visio will merely create an instance of the master in the Document Stencil.
However, if you edit the master in the Document Stencil, then drag and drop from the original stencil, then Visio will copy the original master again, and create an instance of it. So it appears that Visio has lost your customisations.
To avoid this, you must tick the Match master by name on drop property on the Edit Master / Master Properties dialog available from the right mouse menu of the master in the Document Stencil. This will tell Visio to check for a master with the same name in the Document Stencil, and if it finds one, then use it rather than adding a new master to it. This always works except if the two master shapes are radically different, then Visio may create another master.
The second issue is the realisation that dragging and dropping a Pool / Lane master on to a page actually drops, not just one shape, but five! There will be CFF Container, Phase List, Pool / Lane, Separator and Swimlane List. In other words, all of the elements required for a Cross-Functional Flowchart are automatically added. So, when you add a second Pool / Lane, it automatically drops into the Swimlane List and the Title Bar of the CFF Container shape automatically displays.
To avoid this behaviour, review the CROSS-FUNCTIONAL FLOWCHART ribbon tab when you drop the first the Pool / Lane . You can then untick Show Title Bar and Show Separators. Then these elements will not display when a second and third Pool / Lane is dropped onto the page.