Visio VBA - Switching Layers with a macro

I have a macro that switches from a :
technical layer (with IP addresses and port numbers).
management layer (no IP addresses, just icons and host names
CTRL + T for technical
CTRL + M for managerial
Works fine on one sheet.
On page 2, I just created a technical layer, assigned objects and for some reason, the OPPOSITE is taking place.  CTRL + T is showing me the managerial view.  CTRL + M is showing me the tecnical view.  
Same layer names, different page.  Macro works the opposite way!  "T" is now showing managerial view "M" is now showing technical view.
How  can I fix this?
brothertruffle880Asked:
Who is Participating?
 
Visio_GuyCommented:
Ok, I've updated the VBA to use my snippet from above to switch between the "Tech" and "Management" layers using Ctrl + T or Ctrl + M.
Layer-Switching.vsdFor those interested, below is the VBA code that makes this work, no matter the order of the layers.

Ideally, this code should be placed in a stencil, and that stencil should be open in order for the code to work. When the code is in the document, you will end up with many copies of the code--one for each document based on this one--which can be troublesome.
Option Explicit

Public Const LayerName_Mgmt$ = "Management"
Public Const LayerName_Tech$ = "Tech"

'// ----- Public Procedures ---------------------------------------------------
Public Sub ShowManagementLayer()

  '// Ctrl + M

  Dim pg As Visio.Page
  Set pg = Visio.ActivePage
  
  Call m_showAndHideLayers(pg, LayerName_Mgmt$)
  
  Set pg = Nothing

End Sub
Public Sub ShowTechLayer()

  '// Ctrl + T

  Dim pg As Visio.Page
  Set pg = Visio.ActivePage
  
  Call m_showAndHideLayers(pg, LayerName_Tech$)
  
  Set pg = Nothing

End Sub

'// ----- Private Procedures --------------------------------------------------
Private Sub m_showAndHideLayers(ByRef visPg As Visio.Page, _
                                ByVal sLayerNameToShow As String)
  
  If (visPg.Layers.Count = 0) Then
    Call MsgBox("The active page has no layers!" & vbCrLf & vbCrLf & _
            "No changes to layers will be made.")
    GoTo Cleanup
  End If
  
  '// Try and get the target layer:
  Dim lyrTarget As Visio.Layer, lyr As Visio.Layer
  Set lyrTarget = m_getLayerByName(visPg, sLayerNameToShow)
    
  If (lyrTarget Is Nothing) Then
    '// Layer not found, so don't do anything at all
    Call MsgBox("Layer: '" & sLayerNameToShow & "' was not found!" & vbCrLf & vbCrLf & _
                "No changes to layers will be made.")
    GoTo Cleanup
  Else
    '// The layer was found, turn it visible and active:
    lyrTarget.CellsC(Visio.VisCellIndices.visLayerVisible).ResultIU = 1
    lyrTarget.CellsC(Visio.VisCellIndices.visLayerActive).ResultIU = 1
    
    '// Turn all the other layers invisible and inactive:
    Dim i As Integer
    For i = 1 To visPg.Layers.Count
    
      Set lyr = visPg.Layers.Item(i)
      If (Not (lyr Is lyrTarget)) Then
        lyr.CellsC(Visio.VisCellIndices.visLayerVisible).ResultIU = 0
        lyr.CellsC(Visio.VisCellIndices.visLayerActive).ResultIU = 0
      End If
      
    Next i
  
  End If

  
Cleanup:
    
  '// Cleanup:
  Set lyrTarget = Nothing
  Set lyr = Nothing

End Sub

Private Function m_getLayerByName(ByRef pg As Visio.Page, _
                                  ByVal sLayerName As String) As Visio.Layer

  Set m_getLayerByName = Nothing
  
  Dim lyr As Visio.Layer
  For Each lyr In pg.Layers
    If (StrComp(sLayerName, lyr, vbTextCompare) = 0) Then
      Set m_getLayerByName = lyr
      Exit For
    End If
  Next lyr
  
  '// Cleanup:
  Set lyr = Nothing
  
End Function

Open in new window

0
 
Visio_GuyCommented:
Hi BT,

The layers on the new page might have been created in a different order than on the first page (look at the ShapeSheet for each page). I suspect you used a macro-recording from the first page, which needs a bit of parametrization.

It's best to find a layer by name, rather than depend on some sort of index. Here's some test code that uses a GetLayerByName function to get a Visio layer object:

Public Sub Test()

  Dim lyr As Visio.Layer
  Set lyr = GetLayerByName(Visio.ActivePage, "Connector")
  
  If (Not (lyr Is Nothing)) Then
  
    '// Do something with the layer:
    Debug.Print lyr.Name
  
    '// Example: add a shape to the layer:
    '// lyr.Add (shp)
    
  End If

End Sub
Function GetLayerByName(ByRef pg As Visio.Page, _
                        ByVal sLayerName As String) As Visio.Layer

  Set GetLayerByName = Nothing
  
  Dim lyr As Visio.Layer
  For Each lyr In pg.Layers
    If (StrComp(sLayerName, lyr, vbTextCompare) = 0) Then
      Set GetLayerByName = lyr
      Exit For
    End If
  Next lyr
  
  '// Cleanup:
  Set lyr = Nothing
End Function

Open in new window

0
 
brothertruffle880Author Commented:
Hi Visio Guy:
YES!  
You nailed it.  You precisely stated exactly what I did.
Actually, I created three layers in a different order on some pages.

Can you help me fix it.  I'm not a VBA guru so I'm not sure what your code above does.

I have about 30 pages.  There are actually three layers:  management, technical and logistics.  I would like to set up macros so that a user presses CTRL + T to see the technical layer, CTRL + M to see the management layer and CTRL + L to see the logistics layer.
0
 
Visio_GuyCommented:
Hi BT,

Do you need to assign shapes to layers, or is that already done?

Ie: do you simply need to flip the visibility of the layers on each page according to the names/keyboard shortcuts?
0
 
brothertruffle880Author Commented:
You are amazing!  Thanks!
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.