" /> Visio Guy » Run VBA Code When Documents Open
Home » Code

Run VBA Code When Documents Open

Submitted by on May 25, 2007 – 6:25 am | | 60679 views 11 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:

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.

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.


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.


  • 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


  • […] to run VBA code in Visio, have a look at the following articles: John Goldsmith: Just For Starters, Run VBA Code When Documents Open and VBA Macro […]

  • bernardes says:

    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



    End Sub

    André Luiz Bernardes
    A&A® – Work smart, not hard.
    Blog Office VBA | Blog Excel | Blog Access

  • Visio Guy says:

    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!

  • Dave WIlson says:

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


  • Dave WIlson says:

    Ok, I got it running.

  • Dev says:

    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?

  • Visio Guy says:

    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),

  • Dev says:

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

  • ChrisB says:

    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:

    Private Sub Document_ShapeAdded(ByVal Shape As IVShape)

    Dim mastObj As Master
    Dim VApp As Application
    Dim pgObj As Page

    Set VApp = Visio.Application

    'Get the Master property of the shape.
    Set mastObj = Shape.Master
    'Check whether the shape has a master. If not, the shape was created locally.
    If Not (mastObj Is Nothing) Then
    'Check whether the master is "Square".
    If Left(mastObj.Name, 12) = "Script Block" Or Left(mastObj.Name, 5) = "Table" Then
    Set pgObj = VApp.ActiveDocument.Pages(1)
    pgObj.Shapes(mastObj.Name).CellsSRC(visSectionObject, visRowEvent, _
    visEvtCellDblClick).FormulaU = "RUNMACRO(""Tech_Design.Module2.Process_Shape"")"
    Debug.Print "Setting Double-Click to 'Run Macro' for '" & mastObj.Name & "'"
    End If
    End If
    End Sub

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

    Checking Debug Mode...
    Debug Mode = True
    Setting Double-Click to 'Run Macro' for 'Table'

    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,


Leave a comment!

Add your comment below, or trackback from your own site. You can also subscribe to these comments via RSS.

Be nice. Keep it clean. Stay on topic. No spam.

You can use these tags:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

This is a Gravatar-enabled weblog. To get your own globally-recognized-avatar, please register at Gravatar.