VBA: How to select all shapes not assigned to any layer

Started by DanWild, September 07, 2021, 04:32:13 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

DanWild

Hi there

What I want to achieve is that all shapes that are not assigned to any layer get selected so that the user can see them and go for further action.

I've tried for hours but I can't figure out to do it and couldn't find code snippets. I also tried to record a macro which invokes the built in select shapes on layers and the top option which selects the shapes on no layer. That didn't work either.

Hints and code snippets are very welcome. Thank you in advance.

Surrogate

#1
Just write from phone:
You must iterate all shapes and check property LayerMembership LayerMember, if it is empty then shape not assigned to any layer.


PS also you can use property LayerCount
Dim sh As Shape
For Each sh In ActivePage.Shapes
If sh.LayerCount = 0 Then MsgBox sh.NameID & " not assigned to any layer"
Next

DanWild

Thanks to Surrogate for your swift assistance.

I'm not sure if I miss objects with my solution below (subshapes, grouped shapes) or if anything else might lead to an undesired outcome. I mainly struggled with the selection object but now it seems to work. Now, i can use the selection for further action to make sure that there are no shapes that are not on any layer.

Sub SelectShapesNotAttachedToAnyLayer()

    Dim vsoSelection As Visio.Selection                 ' create Selection Object to build selection in memory (not to be seen by user)
    Set vsoSelection = Application.ActiveWindow.Page.CreateSelection(visSelTypeEmpty)
    Application.ActiveWindow.Selection = vsoSelection   ' cancel selection in ActiveWindow
   
    Dim shpObj As Visio.Shape
    For Each shpObj In ActivePage.Shapes                ' iterate over all shapes on ActivePage
        If shpObj.layerCount = 0 Then                   ' if shape not assigned to any layer
            vsoSelection.Select shpObj, visSelect       ' Add this shape to the selection in memory
        End If
    Next shpObj
             
    Application.ActiveWindow.Selection = vsoSelection   ' present the selection to the user
   
End Sub


At first I startet by recording a macro and changed it a bit. Also here, this seems to work and needs almost no code but I guess this only works with my current German language setting and there are different user settings. Is there a constant for {keine Ebene} {no layer} as in the respective dialog?

Sub SelectShapesNotAttachedToAnyLayerFromMacroRecorder()
    Dim vsoSelection As Visio.Selection
    ' This seems to be a problem with different language settings. GER = {Keine Ebene} / ENG {No Layers}
    Set vsoSelection = Application.ActiveWindow.Page.CreateSelection(visSelTypeByLayer, visSelModeSkipSuper, "{Keine Ebene}")
    Application.ActiveWindow.Selection = vsoSelection
End Sub





DanWild

And it is crashing again and i finally found out why. It happens if there are guide lines on the page that are not visible and I try to show the selectionObject in the activewindow.

I therefore changed the code which now just ignores guide lines (shpObj.Type = visTypeGuide). Is there an easier (one line) approch to solve my problem which is to select all shapes that are not assigned to any layer?

Sub SelectShapesNotAttachedToAnyLayer()

    Dim vsoSelection As Visio.Selection                     ' create Selection Object to build selection in memory (not to be seen by user)
    Set vsoSelection = Application.ActiveWindow.Page.CreateSelection(visSelTypeEmpty)
    Application.ActiveWindow.Selection = vsoSelection       ' cancel current selection in ActiveWindow
   
    Dim shpObj As Visio.Shape
    For Each shpObj In ActivePage.Shapes                    ' iterate over all shapes on ActivePage
        If shpObj.layerCount = 0 Then                       ' if shape not assigned to any layer
            If shpObj.Type = visTypeGuide Then
                Debug.Print "--> Guide: " & shpObj.Name     ' visTypeGuide would throw error, not when added to vsoSelection,
                                                            ' but when presenting to user if guide lines are not visible.
            Else
                Debug.Print "    Shape: " & shpObj.Name
                vsoSelection.Select shpObj, visSelect       ' Add this shape to the selection in memory
            End If
        End If
    Next shpObj
             
    Application.ActiveWindow.Selection = vsoSelection       ' present the selection to the user
   
End Sub

Surrogate

#4
Quote from: DanWild on September 08, 2021, 02:24:42 PMIs there an easier (one line) approch to solve my problem which is to select all shapes that are not assigned to any layer?
There is definitely no such possibility!
You even cant define which shapes assigned to some layer without iteration.

DanWild

Quote from: Surrogate on September 08, 2021, 03:29:27 PM
Quote from: DanWild on September 08, 2021, 02:24:42 PMIs there an easier (one line) approch to solve my problem which is to select all shapes that are not assigned to any layer?
There is definitely no such possibility!
You even cant define which shapes assigned to some layer without iteration.

Thanks once more for your assistance. By the way, why is this site still not secured with https?

wapperdude

It occurred to me that if you make all layers hidden, then, the only shapes visible are not members of any layer.  These could then be selected and dealt with as desired.

The following code deletes the non-layered shapes only.

Sub Macro1()

    Dim vsoLayer As Visio.Layer
    Dim vsoLayers As Visio.Layers
   
    Set vsoPage = ActivePage
    Set vsoLayers = vsoPage.Layers
   
    For Each vsoLayer In vsoLayers
        vsoLayer.CellsC(visLayerVisible).FormulaU = "0"
    Next
   
    ActiveWindow.DeselectAll
    ActiveWindow.SelectAll
    ActiveWindow.Selection.DeleteEx (visDeleteNormal)
   
    For Each vsoLayer In vsoLayers
        vsoLayer.CellsC(visLayerVisible).FormulaU = "1"
    Next

End Sub


Modify as needed.
Visio 2019 Pro