Solved

Visio VBA 2013 - 20 page visio file - I need the four buttons on each page to refer to the same four macros  throughout the file.

Posted on 2014-01-24
10
948 Views
Last Modified: 2014-02-14
I have four macro buttons (ActiveX) on every page of my 20 page visio file.
Each macro switches to another layer in that page.  The layers are named the same  on every page: "Level 1 layer", "Level 2 layer", Level 3 layer", "level 4 layer"

I want the four macro buttons to switch layers.    the caption on the buttons read "layer 1", "Layer 2", etc.  On each page I will have thus:

Page one:  Four buttons:
Layer one button
Layer two button
Layer three button
Layer four button

Page two:  Four buttons:
Layer one button
Layer two button
Layer three button
Layer four button

I want the layer one button on page 1, 2, 3, etc.  to always run to the layer one macro
I want the layer two button on page 1, 2, 3, etc. to always run to the layer two macro

It seems that I have to copy and paste the switch layer VBA code over and over for each button on every page!   There's gotta be a shorter path.


Currently when I paste the four buttons on a new page, it doesn't run any macro. It seems kind of wasteful that I'd have to AGAIN code event procedures for each of the four buttons on each of the 20 pages.

When I attempt to rename the newly pasted button from  CommandButton5_Click() to CommandButton1_Click()  I get the message "Ambigous name detected"  and yet,  I WANT the command button1_click() event procedure to run when I click the newly pasted button!
0
Comment
Question by:brothertruffle880
  • 5
  • 5
10 Comments
 
LVL 30

Expert Comment

by:Scott Helmers
ID: 39806679
I was in the process of responding to your previous question on this subject when I noticed you'd closed it and opened this one... so here you go.

Here's a solution that eliminates the need for userforms and capitalizes on the fact that Visio shape names are unique per page and not per document. Consequently, you can copy your four special shapes to every page in your document with no concern about shape names.

The code uses two events of the Window object:
WindowTurnedToPage to determine the current page and to set shape objects to your four special shapes
MouseDown to determine where the user clicked within the window

At the moment the code displays the results of mouse clicks in the Immediate window. You can modify the code by changing the four shape name constants to match your four shapes. When you run the code, the object ThisShape will be set to the button on which the user clicked or will have a value of nothing if the user clicks anywhere other than the four buttons.
Determine-which-of-four-shapes-w.vsd
0
 

Author Comment

by:brothertruffle880
ID: 39811423
HI Scott:  I uploaded a portion of my diagram.
As you can see, I first used the shape double-click behavior  (See upper right corner) to make the diagram switch to different layers.  This was too cumbersome as my managers wanted a way to click directly into a particular layer.
Then, I tried buttons (See last page upper right corner ) and that's where I ran into problems.  (re: myposting here)
Can you help me with inserting  the code you created?
test.vsdm
0
 
LVL 30

Accepted Solution

by:
Scott Helmers earned 500 total points
ID: 39812918
I've reorganized the code slightly to make it easier to reuse. I also created a DocumentOpened event that will initialize the code automatically each time the document is opened. To use it:
paste the code into the ThisDocument module
change my dummy shape names ("AAA", "BBB"...) to match the names of your four shapes
insert your layer switching code in the "TaskActionOnClick" sub (note: the object ThisShape is the one on which the user clicked)
Option Explicit

Dim WithEvents ThisWin As Visio.Window

Dim ThisPage    As Visio.Page
Dim ThisShape   As Visio.Shape

Dim shape1      As Visio.Shape
Dim shape2      As Visio.Shape
Dim shape3      As Visio.Shape
Dim shape4      As Visio.Shape

Const name1     As String = "AAA"       ' name of button 1
Const name2     As String = "BBB"       ' name of button 2
Const name3     As String = "CCC"       ' name of button 3
Const name4     As String = "DDD"       ' name of button 4

Sub TakeActionOnClick()
' This sub is called from the MouseDown event handler if user has clicked on one of the button shapes

    ' delete or comment out this test line after inserting real code
    Debug.Print ThisPage.name, ThisShape.name

    '
    ''
    ''' do something useful here
    ''
    '

End Sub

Private Sub Document_DocumentOpened(ByVal Doc As IVDocument)
' set these objects when document is opened in order to activate event code

    Set ThisWin = ActiveWindow
    Set ThisPage = ActivePage
    Set shape1 = ThisPage.Shapes(name1)
    Set shape2 = ThisPage.Shapes(name2)
    Set shape3 = ThisPage.Shapes(name3)
    Set shape4 = ThisPage.Shapes(name4)

End Sub

Private Sub ThisWin_WindowTurnedToPage(ByVal Window As IVWindow)
' reset page and shape objects whenever user changes to a different page

    Set ThisPage = ActivePage
    ' NOTE: technically, the lines below aren't necessary because the four shape names are
    ' the same on every page, but it feels more complete to do this!
    Set shape1 = ThisPage.Shapes(name1)
    Set shape2 = ThisPage.Shapes(name2)
    Set shape3 = ThisPage.Shapes(name3)
    Set shape4 = ThisPage.Shapes(name4)

End Sub

Private Sub ThisWin_MouseDown(ByVal Button As Long, _
                              ByVal KeyButtonState As Long, _
                              ByVal x As Double, _
                              ByVal y As Double, _
                              CancelDefault As Boolean)
' use x and y values passed into sub to determine whether the user's click on the page resides within
' one of the four special shapes; if so, set global variable 'ThisShape' to the clicked shape

    Set ThisShape = Nothing

    If fbIsInShape(shape1, x, y) Then
        Set ThisShape = shape1
    ElseIf fbIsInShape(shape2, x, y) Then
        Set ThisShape = shape2
    ElseIf fbIsInShape(shape3, x, y) Then
        Set ThisShape = shape3
    ElseIf fbIsInShape(shape4, x, y) Then
        Set ThisShape = shape4
    End If

    If Not ThisShape Is Nothing Then
        Call TakeActionOnClick
    End If

End Sub

Function fbIsInShape(shp As Visio.Shape, x As Double, y As Double) As Boolean
' determines whether the x/y coordinates reside within a specific shape

    Dim px As Double, py As Double          ' PinX and PinY for shape
    Dim w As Double, h As Double            ' Width and Height for shape
    
    Dim x1 As Double, x2 As Double          ' left- and right-most X value for shape
    Dim y1 As Double, y2 As Double          ' bottom- and top-most Y value for shape
    
    px = shp.Cells("PinX")
    py = shp.Cells("PinY")
    w = shp.Cells("Width")
    h = shp.Cells("Height")

    x1 = px - w / 2                         ' left side of shape
    x2 = px + w / 2                         ' right side of shape
    y1 = py - h / 2                         ' bottom side of shape
    y2 = py + h / 2                         ' top side of shape
    
    If (x > x1) And (x < x2) And (y > y1) And (y < y2) Then
        fbIsInShape = True
    Else
        fbIsInShape = False
    End If

End Function

Open in new window

0
 

Author Comment

by:brothertruffle880
ID: 39818700
What does
 Debug.Print ThisPage.name, ThisShape.name
do?

I never used debug.print
0
 
LVL 30

Expert Comment

by:Scott Helmers
ID: 39818820
It's a programmer convenience -- it displays values (the page and shape name in this case) in something called the "Immediate" window in the VB Editor.

If the window is not already open below the code window in the VB editor, select View>Immediate Window to open it. Then when you run my code you'll see the results of clicking on the four shapes.
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 

Author Comment

by:brothertruffle880
ID: 39822210
I'm getting some oddities while trying to modify the code.
I'm using the code to switch to different layers.  I integrated that code with an earlier set of procedures.
0
 

Author Comment

by:brothertruffle880
ID: 39822215
I'm getting some oddities while trying to modify the code.
I'm using the code to switch to different layers.  I integrated that code with an earlier set of procedures.
Determine-which-of-four-shapes.vsd
0
 
LVL 30

Expert Comment

by:Scott Helmers
ID: 39822795
A couple of things:
You used the first version of the code that I posted and not the second version; the second version was organized a bit better and was also set up to be launched automatically each time you (or a user) opens the document.
I assumed you already had buttons with names -- you changed the constants for the button names but the diagram still has my buttons in it. You either need to use your buttons or change the names of my buttons (and the labels on them) to match the name constants. (You change a shape name by selecting the shape and then clicking Developer>Shape Name.)

Once you've got that much set up, see the instruction with the second set of code regarding the "TaskActionOnClick" sub -- that's where you'll put the code that calls the appropriate layer activation sub. Are you familiar with using a CASE statement? It's the perfect VB construct for a situation like this where you want to do one of four things depending which shape the user clicks. (Hint: the code will make the decision about which sub to call based on ThisShape.Name.)

See whether you can get things working based on the above. If you still need more help, just ask -- that's what we're her for!
0
 
LVL 30

Expert Comment

by:Scott Helmers
ID: 39823080
One other observation about your code: VB doesn't allow public constants, which is why the four lines at the top of your code that start with "Public Const..." are red. Remove "Public" and they will be fine.
0
 

Author Closing Comment

by:brothertruffle880
ID: 39859056
Thanks Scott!
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

This is pretty cool.  The purpose of this VB Script is to help you document where JAR (Java ARchive) files and specifically java class files are located so that you can address issues seen with a client or that you can speak intelligently with a dev…
It was really hard time for me to get the understanding of Delegates in C#. I went through many websites and articles but I found them very clumsy. After going through those sites, I noted down the points in a easy way so here I am sharing that unde…
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now