Search code examples
arraysvbavisio

Visio VBA trying to get a list of containers and member shapes


Background: I have some code that runs through a Visio page and returns all the shapes. Many of these shapes are in containers, so I would like to know what container a shape belong to.

Original approach: I was hoping to retrieve the "parent" container of each shape (I only need one level of container, there are no containers within containers) using the Shape.ContainingShape property but that was only returning '0' for every shape.

If anyone has a solution for how I was originally trying to get the container, that would be the most elegant. But since I can't get that to work, I am trying the following alternative, which is also presenting a roadblock.

Current approach: I was able to get a list of all the containers on the page, and now I would like to pull the member shapes for each container. It's not as clean, but it would allow me to cross-reference the shapes and get the containers they belong to.

Issue: I am getting "Error 13 Type Mismatch" when trying to create an array with column 0 being the container name, and column 1 being the member shapes.

' Create array of containers and member shapes
Dim arr() As Long
Dim vsoMemberShape As Shape
Dim vsoContainerShape As Shape
Dim containerArr() As Long
Dim rows As Integer
Dim i As Integer

For Each ContainerID In vsoPage.GetContainers(visContainerIncludeNested)

    Set vsoContainerShape = vsoPage.Shapes.ItemFromID(ContainerID)
    arr = vsoContainerShape.ContainerProperties.GetMemberShapes(1)
    rows = UBound(arr)
    ReDim containerArr(0 To rows, 0 To 1)
    For i = 0 To UBound(arr)

        Set memberShape = vsoPage.Shapes.ItemFromID(arr(i))
        containerArr(i, 0) = vsoContainerShape.NameU
        containerArr(i, 1) = vsoMemberShape.NameU

    Next

Next

' The following code is in a For loop, not shown
' shapeToName is what I want to compare to the member shapes in the container 
' array defined above, and then retrieve the corresponding container
' This is where the error is popping up
shapeToName = CStr(vsoShapeTo.Name)

Dim x As Integer
x = Application.Match(shapeToName, Application.Index(containerArr, 0, 1), 0)
shapeContainer = containerArr(x, 1)

Solution

  • I think what you're looking for is Shape.MemberOfContainers, which returns an array of containers that a shape is a member of.

    You can also have a look at this post which covers the same issue:

    Visio: How to get the shapes that are contained in one shape?

    I'll also throw in a link to a post by David Parker that covers containers in the context of cross-functional flowchart, which makes good use of Containers and Lists:

    https://bvisual.net/2009/09/07/visio-2010-containment-and-cross-functional-flowcharts/