Site icon bVisual

Toggling Layers On and Off

UPDATE March 2017 : I have now expanded this functionality into an add-in for Visio (see Layer Manager add-in for Visio released ).

Visio layering system is more complex than any CAD system I’ve worked with, and often catches users out.  A Visio shape can belong to no layer, one layer or multiple layers simultaneously, and a layer can be visible or invisible; printable or non-printable.  In fact, you can have a shape on a layer that is invisible but printable – a good way to put a watermark across a document.

Firstly, Visio layers are per page in a document, and secondly, Visio layers are stored as an index number with an associated name.  Therefore, layer 1 on page 1 could be named Outline, but layer 1 on page 2 could be called something completely different!

View > Layer Properties will show you the layer settings on the active Visio page, but the # column, which gives you a count of shapes on each layer, can be misleading because the same shape can be on multiple layers, and even sub-shapes (those inside a grouped shape) are counted.

image

Layers have nothing to do with Z-order, therefore a shape on layer 1 may be behind or in-front of a shape on layer 2.  The commands Bring To Front, Bring Forwards, Send To Back and Send Backwards change the Z-order, not the layer.

Usually, you want to be able to quickly switch a layer of and on, however the manual method using the Layer Properties dialog requires you to open it first, then to click both the Visible and Print columns for the layer.  This can get even more complicated when you consider that you usually want to toggle the visibility/printability of a group of layers simultaneously.

To demonstrate the complexity of layers, and as a practical visual aid, I have created the Toggle Layer Button shape.  This shape is based on the Colored block master on the Marketing Diagrams stencil.  I have added a Circle shape into the Master group so that you can easily see if a particular layer, or group of layers, is on or off.  Also, the Circle shape adopts any layer colors assigned.

Download files from here: Toggle Layers.vssm

The Toggle Layer Button shape has a number of right mouse actions, and a double-click action.  The first right mouse action to use is Read Shapes Layers which will run the ReadShapesLayers macro, but first you need to select the button shape then SHIFT+Select the other shapes whose layers you want to assign to the button.

The double-click event runs the DoToggleLayers macro, which will read the layers listed in the text of the button, and then toggle the visibility/printability of each of them.

In the first example, the flowchart comprises of three Flowchart shapes, which are on the Flowchart layer, connected by two Dynamic connectors, on the Connector layer.  I have used one button that is assigned to the Flowchart layer, and one which is assigned to the Connector layer.

In the second example, I grouped the flowchart and assigned the layer, called Both, to the group, with preserver Group Member Layers checked.  I then assigned the button to the group shape, which thus read all of the layers of the group and sub-shapes.

In the third example, I removed the Both layer assignment of each sub-shape, leaving them only on their original layer.  The group shape is assigned to the Both layer only.

Then I clicked the Flowchart button, which turned off the visibility/printability of the Flowchart layer.  Notice that the Circle sub-shape of the Flowchart button is invisible, indicating that the Flowchart layer is switched off.  Also notice that the Flowchart shapes in the second column are still visible because they are also assigned to the Both layer.

I then toggled the Flowchart button again, and toggled the Connector button off.  This time the Dynamic connector shapes are invisible.

I then toggled the button that is assigned to all three layers, causing all layers to be invisible.

Finally, I toggled all layers back on and toggled off just the Both layer.  This caused all shapes to be visible, but only the un-grouped flowchart on the left is selectable.

The other use for the Circle shape is to indicate the colors assigned to each layer.  This is done automatically when you use the Layer Properties dialog.

So, just having the Both layer visible/printable and with Cyan color assigned to it, results in all but the center flowchart being invisible.

I placed the Toggle Layer Button on a stencil called Toggle Layer, and included the following VBA code in the stencil project.  I also included code to change the Z-Order of assigned layers too, just for good measure:

Option Explicit

Public Sub DoToggleLayers(ByRef shp As Visio.Shape)
Dim pag As Visio.Page
Dim lyr As Visio.Layer
Dim aryLayer() As String
Dim sLayer As String
Dim iLayer As Integer

Set pag = shp.ContainingPage
aryLayer = Split(shp.Text, vbCrLf)
For iLayer = 0 To UBound(aryLayer)
sLayer = aryLayer(iLayer)
For Each lyr In pag.Layers
If UCase(lyr.Name) = UCase(sLayer) Then
lyr.CellsC(Visio.visLayerVisible).Formula = Abs(Not (CBool(lyr.CellsC(Visio.visLayerVisible).ResultIU)))
lyr.CellsC(Visio.visLayerPrint).Formula = Abs(Not (CBool(lyr.CellsC(Visio.visLayerPrint).ResultIU)))
Exit For
End If
Next lyr
Next iLayer
End Sub

Private Function getShapesOnLayer(ByVal shpButton As Visio.Shape) As Collection
‘Return a collection of selections
Dim col As New Collection
Dim pag As Visio.Page
Dim lyr As Visio.Layer
Dim sLayer As String
Dim sel As Visio.Selection
Dim aryLayer() As String
Dim iLayer As Integer

Set pag = shpButton.ContainingPage
aryLayer = Split(shpButton.Text, vbCrLf)
For iLayer = 0 To UBound(aryLayer)
sLayer = aryLayer(iLayer)
Set lyr = pag.Layers(sLayer)
‘Only get the top level shapes
Set sel = pag.CreateSelection(visSelTypeByLayer, visSelModeOnlySuper, lyr)
col.Add sel
Next iLayer
Set getShapesOnLayer = col
End Function

Public Sub SendLayersToBack(ByRef shp As Visio.Shape)
Dim col As Collection
Dim iSel As Integer
Dim sel As Visio.Selection
Set col = getShapesOnLayer(shp)
For iSel = 1 To col.Count
Set sel = col.Item(iSel)
sel.SendToBack
Next iSel
End Sub

Public Sub SendLayersBackward(ByRef shp As Visio.Shape)
Dim col As Collection
Dim iSel As Integer
Dim sel As Visio.Selection
Set col = getShapesOnLayer(shp)
For iSel = 1 To col.Count
Set sel = col.Item(iSel)
sel.SendBackward
Next iSel
End Sub

Public Sub BringLayersForward(ByRef shp As Visio.Shape)
Dim col As Collection
Dim iSel As Integer
Dim sel As Visio.Selection
Set col = getShapesOnLayer(shp)
For iSel = 1 To col.Count
Set sel = col.Item(iSel)
sel.BringForward
Next iSel
End Sub

Public Sub BringLayersToFront(ByRef shp As Visio.Shape)
Dim col As Collection
Dim iSel As Integer
Dim sel As Visio.Selection
Set col = getShapesOnLayer(shp)
For iSel = 1 To col.Count
Set sel = col.Item(iSel)
sel.BringToFront
Next iSel
End Sub

Public Sub ReadShapesLayers(ByRef shp As Visio.Shape)
Dim shpSel As Visio.Shape
Dim shpSub As Visio.Shape
Dim sLayer As String
Dim iShape As Integer
Dim sText As String
Dim sFormula As String
Dim dic As New Dictionary

‘Iterate through the selection (exclusing the first shape because it is the button
If Visio.ActiveWindow.Selection.Count > 1 Then
For iShape = 2 To Visio.ActiveWindow.Selection.Count
Set shpSel = Visio.ActiveWindow.Selection.Item(iShape)
getShapeLayers shpSel, dic, sText, sFormula
‘Iterate through sub-shapes
For Each shpSub In shpSel.Shapes
getShapeLayers shpSub, dic, sText, sFormula
Next shpSub
Next iShape
End If
If Len(sText) = 0 Then
sText = “No layers”
sFormula = “”””””
End If
‘Set the text of the indicator Circle sub-shape
shp.Text = sText
‘Set the layers of the indicator Circle sub-shape
shp.Shapes(“Circle”).CellsSRC(Visio.VisSectionIndices.visSectionObject, _
Visio.VisRowIndices.visRowLayerMem, _
Visio.VisCellIndices.visLayerMember).FormulaU = _
“=””” & sFormula & “”””

End Sub

Private Sub getShapeLayers(ByVal shp As Visio.Shape, ByRef dic As Dictionary, _
ByRef sText As String, ByRef sFormula As String)

Dim lyr As Visio.Layer
Dim iLayer As Integer

If shp.LayerCount > 0 Then
For iLayer = 1 To shp.LayerCount
Set lyr = shp.Layer(iLayer)
If dic.Exists(lyr.Name) = False Then
dic.Add lyr.Name, lyr
‘Get the text for the button shape
‘and the formula for the indicator circle
If Len(sText) = 0 Then
sText = lyr.Name
sFormula = lyr.Row
Else
sText = sText & vbCrLf & lyr.Name
sFormula = sFormula & “;” & lyr.Row
End If
End If
Next iLayer
End If
End Sub

Exit mobile version