• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar

Visio Guy

Smart graphics for visual people




  • Home
  • Hire Me
    • Hire Me
    • Résumé
  • Products
    • Products
    • Bubble Revision Shape
    • Layers to Pages Utility
    • Rack Unit Dimension Line
    • Radial Elements Tool with up to 100 Wedges
    • Text on a Circle Visio SmartShape
  • Index
    • Articles by Date
    • YouTube – VisioGuy
    • Download Information
    • Suggestion Box
    • Shop
    • Visio Art
    • Visio Links
    • – Visio Shapes & Stencils
    • – Visio Templates & Drawings
  • About
    • About
    • Donate
    • GitHub
    • jsFiddle
    • Reading List
    • Subscribe & Follow
      • – E-mail
      • – facebook
      • – Twitter
      • – RSS
    • Privacy Policy
  • Discussion Forum
You are here: Home / Development / Code / Run VBA Code When Documents Open

Run VBA Code When Documents Open

May 25, 2007 By Visio Guy 12 Comments

If you’ve dabbled with the VBA project that resides in Visio documents, then you’ve likely stumbled upon the Document object’s DocumentOpened event. This is a great place for running any initialization code that you might require, but there’s a better way…

When you search the events that are fired by the built-in Document object, there are two obvious choices for initialization code that jump out at you: DocumentCreated and DocumenOpened. DocumentCreated fires when a copy of a document is opened (which is what happens by default when you open a Visio template.) DocumentOpened fires, of course, when you open a Visio document.

A better choice, however is RunModeEntered, as we’ll soon see.

The Obvious Startup Events

You can paste the following two subroutines into a Visio document’s VBA project, save the document, then test by opening a copy of the document, or by opening the original version:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Private Sub Document_DocumentCreated(ByVal doc As IVDocument) 
 
  '// This procedure runs when a Visio document is
  '// created.
  '// Ie: when a copy of a document is opened, or a
  '// template (.vst) is opened. In fact, a .vst file
  '// is simply anormal Visio document that happens
  '// to open a copy as a copy by default. That's the
  '// essential difference between a .vst and a .vsd. 
 
  Call MsgBox("Document_DocumentCreated") 
 
End Sub 
 
Private Sub Document_DocumentOpened(ByVal doc As IVDocument) 
 
  '// This procedure runs when a Visio document is
  '// opened. 
  Call MsgBox("Document_DocumentOpened") 
 
End Sub
Private Sub Document_DocumentCreated(ByVal doc As IVDocument) 

  '// This procedure runs when a Visio document is
  '// created.
  '// Ie: when a copy of a document is opened, or a
  '// template (.vst) is opened. In fact, a .vst file
  '// is simply anormal Visio document that happens
  '// to open a copy as a copy by default. That's the
  '// essential difference between a .vst and a .vsd. 

  Call MsgBox("Document_DocumentCreated") 

End Sub 

Private Sub Document_DocumentOpened(ByVal doc As IVDocument) 

  '// This procedure runs when a Visio document is
  '// opened. 
  Call MsgBox("Document_DocumentOpened") 

End Sub

Enter RunModeEntered

The trouble with the two events we’ve discussed becomes evident when you start to (frequently) test your code. You have to keep closing and opening the documents to test the code! Since the initialization code for open-original vs. open-copy is often identical, it makes sense to use the less-well-known event: RunModeEntered.

Document_RunModeEntered is also an event that hangs off of the Document object, just like the other two events we just talked about. The great thing about RunModeEntered is that it fires when you toggle the VBA Design Mode button. The button shows a little blue triangle with pencil and ruler. The button is a toggle button, and it looks like this:

Design Mode On

Design Mode On

Design Mode Off

Design Mode Off

When design mode is off, VBA code won’t execute, so you can “live in peace” and perform certain operations without having to worry about code executing while you are adjusting controls on Windows forms, or Visio shapes and masters.

You’ll find this button in two places:

  • Visio’s Developer toolbar
  • VBA’s Standard toolbar

When you toggle the Design Mode button back to “on”, then the Document_RunModeEntered event fires, and any code in this Sub will execute! No more closing and opening your document just to test! You can paste the Sub below into your VBA project and give it a go.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Private Sub Document_RunModeEntered(ByVal doc As IVDocument) 
 
  '// This procedure runs when a Visio document is
  '// created or opened. It also runs when the VBA
  '// "Design Mode"/ "Exit Design Mode" button is
  '// pressed.
  '//
  '// Since this procedure runs when a document is
  '// opened or created, it serves as a more convenient
  '// place for calling your initialization code,
  '// since you can simply click the little blue
  '// triangle from within the VBA editor, or from
  '// Visio's "Developer" toolbar.
 
  Call MsgBox("Document_RunModeEntered") 
 
End Sub
Private Sub Document_RunModeEntered(ByVal doc As IVDocument) 

  '// This procedure runs when a Visio document is
  '// created or opened. It also runs when the VBA
  '// "Design Mode"/ "Exit Design Mode" button is
  '// pressed.
  '//
  '// Since this procedure runs when a document is
  '// opened or created, it serves as a more convenient
  '// place for calling your initialization code,
  '// since you can simply click the little blue
  '// triangle from within the VBA editor, or from
  '// Visio's "Developer" toolbar.

  Call MsgBox("Document_RunModeEntered") 

End Sub

RunModeEntered is also convenient for resetting a diagram that “has gone wrong.” Of course, we’d all like to write perfect code, but unfortunately, problems do arise. It may be acceptable to tell your users to “Show the Developer toolbar and toggle the Design Mode button off, then on” to reset the diagram. Not an optimal solution, but perhaps a quicker fix than taking users into the VBA project or other icky possibilities.

RunModeEntered isn’t the only solution. You could just write an initialization subroutine, say “m_init”, and call that from DocumentOpened or DocumentCreated. You can put your cursor inside of this subroutine and press F5 to run the code without having to close and re-open the document. But here agian, RunModeEntered can be more convenient, because you can restart the code from the Visio drawing interface. No Alt+Tab-bing back to VBA.

TODO

Information about persistent events that are stored with the document might top-off this article rather nicely.

Persistent Events are events that are stored in a Visio document, but not as VBA code. They can be used to start add-ons or add-ins on document open/create. There is no easy user-interface for editing these events, so they can only be accessed via code.

Examples include the Org Chart Wizard template, and the Cross-functional Flowchart template, both of which present the users with custom-code dialog boxes on open.

See:

  • Document Object > EventList property in the Visio Developer’s Reference help file
  • Microsoft Office Visio Persistent Events Tool that is included with the Visio 2007 SDK
  • Tweet
  • More
  • Pocket
  • Share on Tumblr
  • Print
  • Email

Related posts:

  1. VBA Macro Security

Filed Under: Code Tagged With: Macro, Programming

Previous Post: « Free Visio People Shapes
Next Post: Sales Force Automation With Visio »

Reader Interactions

Comments

  1. Mark Nelson (MS) says

    May 26, 2007 at 6:32 am

    Good tip, Chris!

  2. bernardes says

    December 7, 2010 at 7:29 pm

    Try this too:

    Public Sub ShowNames()

    ‘Declare object variables as Visio object types.
    Dim vsoPage As Visio.Page
    Dim vsoDocument As Visio.Document
    Dim vsoDocuments As Visio.Documents
    Dim vsoPages As Visio.Pages

    ‘Iterate through all open documents.
    Set vsoDocuments = Application.Documents
    For Each vsoDocument In vsoDocuments

    ‘Print the drawing name in the Visual Basic Editor
    ‘Immediate window.
    Debug.Print vsoDocument.FullName

    ‘Iterate through all pages in a drawing.
    Set vsoPages = vsoDocument.Pages
    For Each vsoPage In vsoPages

    ‘Print the page name in the Visual Basic Editor
    ‘Immediate window.
    Debug.Print Tab(5); vsoPage.Name

    Next

    Next

    End Sub

    André Luiz Bernardes
    https://sites.google.com/site/vbabernardes/blogs
    A&A® – Work smart, not hard.
    Blog Office VBA | Blog Excel | Blog Access

  3. Visio Guy says

    December 7, 2010 at 10:41 pm

    Well, um, for those reading the comments, Bernardes’ code prints the name of every document that is open in Visio, along with the name of every page in every document.

    Perhaps he didn’t quite understand what this article was about, but thanks anyway.

    Say “Hi” to Walter, Bernardes!

  4. Dave WIlson says

    February 1, 2012 at 10:45 pm

    How do I make it run? Put the code in and nothing happens.

    Thanks.
    Dave

  5. Dave WIlson says

    February 2, 2012 at 12:18 am

    Ok, I got it running.

  6. Visio Guy says

    February 3, 2012 at 5:28 pm

    @Dave,

    Phew!

  7. Dev says

    March 15, 2012 at 4:45 am

    Hey,
    Is there a way to have a macro implemented within Visio without creating a COM Add-In?

    I have a lot of VBA code, including some Forms, which I don’t want to have to re-create in VS.

    So yeah, wondering if its possible to have a macro load on startup of Visio?

  8. Visio Guy says

    April 12, 2012 at 11:37 am

    Hi Dev,

    One thing you can do is move your macros to a “code stencil” – just a stencil that is used for holding VBA.

    This keeps the code from being copied with every document that is created. Of course, documents need to have the stencil open in order to benefit from the code. You’ll also have to re-think reference to ThisDocument, which will now be the stencil, and probably not what you want. (Use ActiveDocument in most cases, instead.)

    You can also specify a Startup path. Go to: File > Options > Advanced (scroll way down to the bottom) > General > File Locations > Startup.

    I put a stencil and a drawing in their, but they didn’t open on startup. I put a shortcut to Notepad2.exe, and nothing happened. But when I coped Notepad2.exe to the startup directory, it DID open when Visio started. You might be able to put a VB script file in the startup directory that would open a library of helpful VBA functions (contained in a stencil),

  9. Dev says

    April 13, 2012 at 12:16 am

    Thanks Visio Guy! That is exactly what I did, put the macro within a stencil. So useful, so portable now.

  10. ChrisB says

    June 25, 2013 at 11:24 am

    Hi Chris,

    Thanks again for the help you’ve already given (Master Shapes, Sub-selecting shapes, etc., etc.).

    The final (possibly) part of my challenge is to programatically change the default double-click behaviour of a shape dropped onto my ‘Process’ page – logically the following code should work (and has been tested in step mode to prove it works:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    <br />
    Private Sub Document_ShapeAdded(ByVal Shape As IVShape)</p>
    <p>    Dim mastObj     As Master<br />
        Dim VApp        As Application<br />
        Dim pgObj       As Page</p>
    <p>    Set VApp = Visio.Application</p>
    <p>    'Get the Master property of the shape.<br />
        Set mastObj = Shape.Master<br />
        'Check whether the shape has a master. If not, the shape was created locally.<br />
        If Not (mastObj Is Nothing) Then<br />
            'Check whether the master is "Square".<br />
            If Left(mastObj.Name, 12) = "Script Block" Or Left(mastObj.Name, 5) = "Table" Then<br />
            Set pgObj = VApp.ActiveDocument.Pages(1)<br />
                pgObj.Shapes(mastObj.Name).CellsSRC(visSectionObject, visRowEvent, _<br />
                    visEvtCellDblClick).FormulaU = "RUNMACRO(""Tech_Design.Module2.Process_Shape"")"<br />
                    Debug.Print "Setting Double-Click to 'Run Macro' for '" & mastObj.Name & "'"<br />
            End If<br />
        End If<br />
    End Sub<br />
    <br />
    Private Sub Document_ShapeAdded(ByVal Shape As IVShape)</p>
    <p>    Dim mastObj     As Master<br />
        Dim VApp        As Application<br />
        Dim pgObj       As Page</p>
    <p>    Set VApp = Visio.Application</p>
    <p>    'Get the Master property of the shape.<br />
        Set mastObj = Shape.Master<br />
        'Check whether the shape has a master. If not, the shape was created locally.<br />
        If Not (mastObj Is Nothing) Then<br />
            'Check whether the master is "Square".<br />
            If Left(mastObj.Name, 12) = "Script Block" Or Left(mastObj.Name, 5) = "Table" Then<br />
            Set pgObj = VApp.ActiveDocument.Pages(1)<br />
                pgObj.Shapes(mastObj.Name).CellsSRC(visSectionObject, visRowEvent, _<br />
                    visEvtCellDblClick).FormulaU = "RUNMACRO(""Tech_Design.Module2.Process_Shape"")"<br />
                    Debug.Print "Setting Double-Click to 'Run Macro' for '" & mastObj.Name & "'"<br />
            End If<br />
        End If<br />
    End Sub<br />

    When I drop a table shape on the form, it does appear to run (uninterrupted mode) as my debug log shows:

    1
    2
    3
    4
    
    <br />
    Checking Debug Mode...<br />
    Debug Mode = True<br />
    Setting Double-Click to 'Run Macro' for 'Table'<br />
    <br />
    Checking Debug Mode...<br />
    Debug Mode = True<br />
    Setting Double-Click to 'Run Macro' for 'Table'<br />

    The same is true for the Script Blocks – however, when I then look at the default behaviour of the new object, it is not set to ‘Run Macro’ but ‘Edit Shapes Text’.

    I know it’s probably obvious, but what am I missing here?

    Thanks again,

    Chris

  11. make says

    September 27, 2019 at 5:10 am

    Hi all,
    i have found this thread, and i want to ask you for help.
    I am trying to use command buttons in visio to hide different layers. But i want to use them also to hide some of other command buttons or textfields buttons. The thing is, if i add the specific command button to the hidden layer sometimes it doesnt hide. when i enter/exit design mode, it hides corectly.(like a refresh or what)
    so i wanted to do a macro, which will just enter/exit design mode to refresh the diagram.

    I thought i can use the “RunModeEntered” function, but it doesnt trigger when i click on the design button to enter design mode, it triggers only to leave design mode.
    So i dont know how to use this function correctly.

    Please help.

Leave a Reply Cancel reply

Primary Sidebar

Buy Text on a Circle Shape
Article — Video — Purchase

Categories

Buy my book!

Meta

  • Log in
  • Entries feed
  • Comments feed
  • WordPress.org

Tag Cloud

A/V Artistic Effects BPM Code Connectors Control Handles Countries Custom Patterns Custom Properties Data Graphics Data Linking Data Visualization David Edson David Parker Fill Format Formulas Functions Geometry Gradient Images Links Maps Multi-shapes Network Programming repeating shapes Resources Right-Click Actions Scale Shape Data ShapeSheet ShapeSheet Formulas ShapeSheet Functions SharePoint shiny SmartShapes Sport Sports Text Themes Tools Transparency User-defined Cells Visio 2007 Visio SmartShapes

Top Posts & Pages

  • - Visio Shapes & Stencils
  • - Visio Templates & Drawings
  • Sankey Diagram Shapes for Visio
  • Go 3D with Free Isometric Piping Shapes for Visio
  • Amazon AWS Visio Shapes
  • Bubble Revision Shapes
  • Text on a Circle Visio Shape
  • Visio Network Server Shape Icon Customization Tool
  • Audio Visual Components Shapes
  • Text to the Bottom of the Shape

www.visguy.com - Visio Guy - since 2006

 

Loading Comments...