Site icon bVisual

A Visio List Shape is also a Container

Structured diagrams have been around in Microsoft Visio since 2010 and I have always known that list shapes are a specialized container shape, however it still came as a surprise to me recently that a list shape can simultaneously act as a container shape!

There are a few examples of both container and list shapes in the Microsoft provided content in all versions of Visio desktop, and even in the subscription Visio for web. The most popular of these is the Cross-Functional Flowchart template which contains container shapes (the Swimlane and Separator shapes) within list shapes (Swimlane List and Phase List), which are within another container shape (CFF Container).

In Visio desktop, the Insert / Diagram Parts / Container allows you to choose from a number of pre-built container shapes. There is no button to insert a list shape, but you can create your own or easily modify one of the pre-built ones to behave as a list shape.

In this example, I just added a

I renamed the master as Belt List and ticked the Match master by name on drop option, then changed the User.msvStructureType value to List from Container, and added the seven additional User-defined Cells rows as listed in the List Shape Details section in the Custom Containers, Lists and Callouts in Visio 2010 article.

Then I added visHeadingText, which is copied from the Swimlane shapes (and should be in all of the Microsoft-provided container shapes!), with the formula:

=SHAPETEXT(Sheet.8!TheText)

This means that I will have access to the container text from any member shapes.

So now I have a list shape that will order member shapes from top to bottom… notice that the original Belt List shape has not yet realized that it has been made into a list… simply moving the old members will sort that out.

So far, this container will assume that everything dropped into it needs to become a list member, so now I want to make it more selective by adding in some more cells into the potential member shapes.

First, I added a special User-defined Cell, msvShapeCategories, to both the circle and rectangle shapes, with the value “Circle” and “Rectangle” respectively.

Next, I added three Shape Data rows, Container, ListPosition and Page to them with the following formulas, which are guarded to prevent editing in the UI:

=GUARD(IFERROR(LISTSHEETREF()!User.VISHEADINGTEXT,IFERROR(CONTAINERSHEETREF(1)!User.VISHEADINGTEXT,"")))
=GUARD(LISTORDER())
=GUARD(PAGENAME())

I also inserted the Prop.ListPosition as the text, and dragged them onto the Document Stencil and named them as Circle and Rectangle.

So, if I then insert these into the User.msvSDListRequiredCategories value of the Belt List master shape, it will only allow shapes with these categories to be inserted into the list.

I could add multiple instances of these shapes and they will inherit values from the list shape and page.

However, if I then remove Circle from User.msvSDListRequiredCategories and, instead, insert it into User.msvSDContainerRequiredCategories, then I will get different behavior.

The Circle shapes can be placed anywhere within the container, and they still recognize that they are within it, and will move with it. The Rectangle shapes still behave as list members.

Fortunately, the Visio API provides methods to get the shape ids of the list and container members separately. So, in VBA, the following sub will write out the names of the member shapes of the selected container shape:

Public Sub WriteMembers()
Dim shpContainer As Visio.Shape
Dim pag As Visio.Page
    Set shpContainer = ActiveWindow.Selection.PrimaryItem
    Set pag = ActivePage
Dim aryListMemberIDs() As Long
    aryListMemberIDs = shpContainer.ContainerProperties.GetListMembers()

Dim i As Integer
    Debug.Print "List Members of " & shpContainer.Name
    For i = 0 To UBound(aryListMemberIDs)
        Debug.Print , pag.Shapes.ItemFromID(aryListMemberIDs(i)).Name
    Next i
Dim aryContainerMemberIDs() As Long
    aryContainerMemberIDs = _
        shpContainer.ContainerProperties.GetMemberShapes( _
            Visio.VisContainerFlags.visContainerFlagsExcludeListMembers)
    Debug.Print "Container Members of " & shpContainer.Name
    For i = 0 To UBound(aryContainerMemberIDs)
        Debug.Print , pag.Shapes.ItemFromID(aryContainerMemberIDs(i)).Name
    Next i
End Sub

The output to the Immediate Window is:

List Members of Belt List.1011
              Rectangle.1019
              Rectangle.1017
Container Members of Belt List.1011
              Circle.1016
              Circle.1018
              Circle.1020
              Circle.1021
              Circle.1022

A similar count can be retrieved in the ShapeSheet, as in the following example where I inserted custom formulas into the text of two associated Callout shapes.

The callout on the left has the custom formula inserted:

="List Members="&CALLOUTTARGETREF()!LISTMEMBERCOUNT()

The callout on the right has the custom formula inserted:

="Container Members="&CALLOUTTARGETREF()!CONTAINERMEMBERCOUNT()

I will store this knowledge away for future use, but I thought I would share this in case others find it useful.

See https://docs.microsoft.com/office/client-developer/visio/listsheetref-function and https://docs.microsoft.com/office/client-developer/visio/containersheetref-function for ShapeSheet function information.

See https://docs.microsoft.com/office/vba/api/visio.containerproperties.getlistmembers and https://docs.microsoft.com/office/vba/api/visio.containerproperties.getmembershapes for Visio API information.

Moving Phases/Separators in Visio Cross-Functional Flowcharts?

I use Visio Cross-Functional Flowcharts a lot, but there is one thing that really bugs me … you can move function bands\swimlanes around, but you can’t move the phases\separators in the same way. The phases/separators are containers just like the function bands\swimlanes, so why can’t I move them? Actually, it is quite understandable when you…

Referencing Container Data in Visio

Microsoft Visio has a useful Structured Diagramming concept that consists of Containers, Callouts and Connectors. The first of these features make it possible for shapes to know what they are contained within, as a better option to grouping shapes together. Grouping can hide or break the grouped shapes smartness, so Visio provides two ways of…

Understanding Morse Clicks with Visio

A few years ago, I wrote an article about messaging and encryption inspired by a visit to the National Museum of Computing in the UK. I developed a Morse Click shape to demonstrate how Visio can be used to represent and learn Morse Code. However, I never published the shapes here, and my good friend…

Visio 2010 MVP Session videos reprise

Back in 2012, my fellow Visio MVPs, Scott Helmers and Chris Roth, and I recorded a series of 24 videos about Visio 2010. They were first hosted on Microsoft’s web site, then they put them up on YouTube, they they got deleted :-(. Well, we have managed to retrieve them, and put them back up…

Using Emojis in Visio

In the new normal of social distancing, we can easily miss the nuances of facial expressions with the the various electronic communication platforms that we utilise. In our personal communications via mobile apps, we have all started to use Emojis to express sentiment and actions, although we can sometimes convey the wrong meanings unintentionally as…

Using CODE() and UNICODE() functions in Visio

Microsoft Visio does have CHAR() and UNICHAR() ShapeSheet functions, just like Excel, but it does not have the inverse CODE() and UNICODE() functions, unlike Excel. However, there is a way to create a formula in the Visio ShapeSheet to provide these functions. The following worksheet demonstrates how the CHAR(), CODE(), UNICHAR(), and UNICODE() functions work…

Exit mobile version