Hi guys!
I'm working on a macro in Visio to automatically draw virtual machine depending their environnment and applications from an SQL Server database.
So far everything works well except when I loop trough container to select shapes inside it to align and distribute them. It works for the first container but when it passes to the second, the code do not find any shapes and an exception error occurs. In step by step I see that shpID is empty even so the container is the good one.
Any ideas?
For Each Pge In Col_Page
'Définit la page active
Application.ActiveWindow.Page = Pge
Application.ActiveWindow.DeselectAll
'Si la page active est la page Accueil ou Index, alors passer à la suivante,
'Sinon passe au crible chaque forme présente sur la page et si une forme est du type serveur
'alors celle-ci est ajouter à la sélection.
'Auto aligne et auto espace les formes dans la sélection
If Pge.Name = "Accueil" Then
Else
If Pge.Name = "Index" Then
Else
Set Col_Shape = Application.ActivePage.Shapes
Set Pge = Application.ActiveWindow.Page
For Each Container In Col_Shape
Set ServerShapeSelect = Application.ActiveWindow.Selection
If Container.Master = "alternative" Then
For Each shpID In Container.ContainerProperties.GetMemberShapes(visContainerIncludeNested)
Set vsoShape = Application.ActivePage.Shapes.ItemFromID(shpID)
If vsoShape.Master = "Serveur" Or vsoShape.Master = "Serveur de base de données" Or vsoShape.Master = "Serveur de fichiers" Or vsoShape.Master = "Serveur de messagerie" Then
Set ShapeSelect = vsoShape
ServerShapeSelect.Select ShapeSelect, visSelect
End If
Next shpID
ServerShapeSelect.LayoutIncremental visLayoutIncrSpace, visLayoutHorzAlignNone, visLayoutVertAlignNone, 1, 1, visInches
ServerShapeSelect.Align visHorzAlignNone, visVertAlignTop, False
If ServerShapeSelect.Count < 3 Then
Else
ServerShapeSelect.Distribute visDistHorzSpace
End If
ServerShapeSelect.LayoutIncremental visLayoutIncrSpace, visLayoutHorzAlignNone, visLayoutVertAlignNone, 1, 1, visInches
Else
End If
Next Container
End If
End If
Next Pge
(https://image.noelshack.com/minis/2019/05/5/1549016619-sans-titre.png) (https://www.noelshack.com/2019-05-5-1549016619-sans-titre.png)
The following code snippet should work. It uses different construct to loop thru containers on a page, it eliminates any "list" container, and then collects the "members" of the selected container for editing:
For Each containerID In ActivePage.GetContainers(visContainerIncludeNested) 'loop thru containers on page
Set vsoContainerShape = ActivePage.Shapes.ItemFromID(containerID)
If vsoContainerShape.ContainerProperties.ContainerType = visContainerTypeNormal Then 'ignore list containers
arr = vsoContainerShape.ContainerProperties.GetMemberShapes(0) 'array collection of container members
For i = 0 To UBound(arr) 'loop thru the members
(your code here)
next
End if
next container
References:
https://blogs.msdn.microsoft.com/visio/2010/01/12/custom-containers-lists-and-callouts-in-visio-2010/ (https://blogs.msdn.microsoft.com/visio/2010/01/12/custom-containers-lists-and-callouts-in-visio-2010/)
https://docs.microsoft.com/en-us/office/vba/api/visio.page.getcontainers (https://docs.microsoft.com/en-us/office/vba/api/visio.page.getcontainers)
https://docs.microsoft.com/en-us/office/vba/api/Visio.ContainerProperties.GetMemberShapes (https://docs.microsoft.com/en-us/office/vba/api/Visio.ContainerProperties.GetMemberShapes)
see also: http://visguy.com/vgforum/index.php?topic=8686.0 (http://visguy.com/vgforum/index.php?topic=8686.0) Contains more coding based links.