• Skip to main content
  • Skip to primary sidebar
  • Skip to footer

bVisual

  • Home
  • Services
    • How Visio smartness can help your business
    • Visio visual in Power BI
    • Visio Consulting Services
    • Visio Bureau Services
    • Visio Training and Support Services
  • Products
    • Visio Shape Report Converter
    • SS Plus
    • LayerManager
    • visViewer
    • Metro Icons
    • Rules Tools for Visio
    • The Visio 2010 Sessions App
    • Multi-Language Text for Visio
    • Document Imager for Visio
    • multiSelect for Visio
    • pdSelect for Visio
  • Case Studies
    • Case studies overview
    • Using Visio in Education for GIS
    • Visualizing Construction Project Schedules
    • Visio Online Business Process Mapping
    • Nexans Visio Template
    • CNEE Projects, WorldCom
    • Chase Manhattan Bank
  • News
    • Recent news
    • News archive
  • Resources
    • Articles➡
      • ShapeSheet Functions A-Z
      • Comparing Visio for the Web and Desktop
      • Customising Visio Shapes for the Web App
      • Key differences between the Visio desktop and web apps
      • Using the Visio Data Visualizer in Excel
      • Using Visio in Teams
      • Creating Visio Tabs and Apps for Teams with SharePoint Framework (SPFx)
      • Designing Power Automate Flows with Microsoft Visio
      • Innovative uses of Visio Lists
    • Webcasts ➡
      • Visio in Organizations
      • My session and other Visio sessions at MSIgnite 2019
      • Power up your Visio diagrams
      • Vision up your Visio diagrams
      • The Visio 2010 MVP Sessions
    • Visio Web Learning Resources
    • Books➡
      • Visualize Complex Processes with Microsoft Visio
      • Mastering Data Visualization with Microsoft Visio
      • Microsoft Visio Business Process Diagramming and Validation
      • Visualizing Information with Microsoft Visio
  • Blog
    • Browse blog articles
    • Visio Power BI articles
    • Visio for Web articles
    • A history of messaging and encryption
  • About us
    • About bVisual
    • Testimonials
    • Bio of David Parker
    • Contact Us
    • Website Privacy Policy
    • Website terms and conditions
    • Ariba Network
You are here: Home / Visio / Visio 2010 / How to Run VBA Macros from a Ribbon Button in Visio 2010

Published on March 14, 2011 by David Parker

How to Run VBA Macros from a Ribbon Button in Visio 2010

A colleague, who is an experienced Visio tutor, asked me how to hook VBA macros to the Fluent UI Ribbon. He figured that it must\should be easy, but he can’t see where it is done. Well, this question has resonance because a plea was made to the Microsoft Visio team at our recent MVP Conference that this often asked for feature should be made easy for the macro developer. Now, I must admit that I have been so busy writing .Net Visio Add-Ins and following the pattern for the Fluent UI in VSTO C# code, that I had not appreciated just how convoluted the calling of VBA from a Ribbon button is. So, I thought I would offer a way of doing this in a simple (I hope!) way.

I will show how this can be done for a Visio drawing or template that contains VBA macros, and how this can be also be used for a Visio stencil that contains the code. I know that some macro developers put their code into drawings, but I would always recommend putting the code into a stencil, if the code is to be used by multiple drawings.

The Visio team’s Insight Blog has some useful background at http://blogs.msdn.com/b/visio/archive/2010/02/24/user-interface-extensibility-in-visio-2010.aspx , but it only has one fleeting mention of VBA macros:

For VBA, you simply provide the contents of a RibbonX XML as a string directly to Visio through the CustomUI property.

So, what does that mean? How do you actually do it?

Well, there is some sample code in the Visio 2016 SDK.

I used this code as a starting point to develop my classes and module that I have included in the download ( see Ribbon Macros.vsd ) for this article. The principle is that the opening of the document will load the custom UI, which will then be removed when the document is closed. I have included the public subs LoadRibbon and UnloadRibbon so that you can set the UI without closing and opening the document repeatedly.

The only change that is required to the code if it is moved into a stencil, id for the ThisDocument parameters to be replaced with Nothing. This will have the effect of enabling any code that is in the stencil whilst it is open. Of course, code in the stencil can be used for any open drawings.

There are four areas in the Fluent UI that can call VBA code:

  • The Ribbon
  • The Backstage View
  • The Context Menus
  • The Commands

I have provided an example for each. If you want to read about the principles of Fluent UI design, then you could start here Microsoft Fluent Design , but I am only showing basic buttons in this example. Feel free to expand the range of controls to suit your requirements…

Another useful resource is Office 2016 Help Files : Office Fluent User Interface Control Identifier . This is a series of Excel files that list all of the built-in control Ids for all of the Microsoft Office documents, and one of them, VisioControls.xlsx, lists those for Visio.

I decided to create some methods in the CustomUI module to return XML snippets for various parts of XML string required to build the Ribbon xml:

I included carriage return line feeds (vbCrlf) and tabs (vbTab) in the XML to make it easier to understand.

All of these XML snippets are called from the getRibbonXML method, so you only need to edit this function to modify the UI. In fact, I have included four parameters in the header of getRibbonXML to make it easier to switch on/off each of the four Fluent UI elements:

Private Function getRibbonXML(ByVal includeCommands As Boolean, _  ByVal includeRibbonTab As Boolean, ByVal includeBackstage As Boolean, _  ByVal includeContextMenus As Boolean) As String

This function is called from IRibbonExtensibility_GetCustomUI method in the Ribbon class.

The Ribbon

You can add groups to existing tabs in the ribbon, but you will most probably want to add your own tab with groups and buttons on it. In my example, I have created a new tab, labeled Custom Ribbon Tab, with a single group, labeled Custom Group, containing a large button, Macro 1; two small buttons, Macro 2 and Macro 3; and a split button, Macro 4.

In fact, the split button contains two menu items, Macro 4 and Macro 5.

All of the buttons have an icon, see the Office 2010 Add-In : Icons Gallery at http://www.microsoft.com/downloads/en/details.aspx?displaylang=en&FamilyID=2d3a18a2-2e75-4e43-8579-d543c19d0eed , and each has a supertip (a longer description) that is displayed on mouse over. Note that the FriendlyName, My custom Fluent UI, is entered in the CustomUIStart method in the CustomUI module.

The code that creates this button can be found in getRibbon method of the Ribbon class:

        'Open the Ribbon element
        strGetRibbonXML2 = getRibbonBegin
        'Open the Tab element
        strGetRibbonXML2 = strGetRibbonXML2 & getTabBegin(False, "tab1", "Custom Ribbon Tab")
        'Open the Group element
        strGetRibbonXML2 = strGetRibbonXML2 & getGroupBegin(False, "group1", "Custom Group")
        'Add custom buttons as required
        strGetRibbonXML2 = strGetRibbonXML2 & getButton( _
            "customMacro1", "Macro 1", "This is macro 1", "GroupSynchronizeWithSite", True)
        strGetRibbonXML2 = strGetRibbonXML2 & getButton( _
            "customMacro2", "Macro 2", "This is macro 2", "GroupViewsInfoPath", False)
        strGetRibbonXML2 = strGetRibbonXML2 & getButton( _
            "customMacro3", "Macro 3", "This is macro 3", "PostReply", False)
        'Open the split button element
        strGetRibbonXML2 = strGetRibbonXML2 & getSplitButtonBegin("customSplit1")
        'Open the menu element
        strGetRibbonXML2 = strGetRibbonXML2 & getMenuBegin("customMenu1")
        'Add custom buttons as required
        strGetRibbonXML2 = strGetRibbonXML2 & getButton( _
            "customMacro4", "Macro 4", "This is macro 4", "VisioDiagramGallery", False)
        strGetRibbonXML2 = strGetRibbonXML2 & getButton( _
            "customMacro5", "Macro 5", "This is macro 5", "VisioTransparency", False)
        'Close the menu element
        strGetRibbonXML2 = strGetRibbonXML2 & getMenuEnd
        'Close the split button element
        strGetRibbonXML2 = strGetRibbonXML2 & getSplitButtonEnd
        'Close the Group element
        strGetRibbonXML2 = strGetRibbonXML2 & getGroupEnd
        'Close the Tab element
        strGetRibbonXML2 = strGetRibbonXML2 & getTabEnd
        'Close the Ribbon element
        strGetRibbonXML2 = strGetRibbonXML2 & getRibbonEnd

 This produces the XML snippet:

<ribbon>  <tabs>  <tab id="tab1" label="Custom Ribbon Tab">  <group id="group1" label="Custom Group">  <button id="customMacro1" label="Macro 1" supertip="This is macro 1" size="large" imageMso="GroupSynchronizeWithSite" onAction="OnAction"/>  <button id="customMacro2" label="Macro 2" supertip="This is macro 2" imageMso="GroupViewsInfoPath" onAction="OnAction"/>  <button id="customMacro3" label="Macro 3" supertip="This is macro 3" imageMso="PostReply" onAction="OnAction"/>  <splitButton id="customSplit1">  <menu id="customMenu1">  <button id="customMacro4" label="Macro 4" supertip="This is macro 4" imageMso="VisioDiagramGallery" onAction="OnAction"/>  <button id="customMacro5" label="Macro 5" supertip="This is macro 5" imageMso="VisioTransparency" onAction="OnAction"/>  </menu>  </splitButton>  </group>  </tab>  </tabs> </ribbon> 

The Backstage View

I have given an example for two columns in the Backstage View, in a new tab labeled Custom Tab. I have included a large button, labeled BS Macro 1 and; and two normal buttons, labeled BS Macro 2 and BS Macro 3.

The code that creates this button can be found in getRibbon method of the Ribbon class:

'Open the backstage element  
strGetRibbonXML3 = getBackstageBegin  
'Open the tab element  
strGetRibbonXML3 = strGetRibbonXML3 & getTabBegin(False, "tab2", "Custom Tab")  
'Open the column element  
strGetRibbonXML3 = strGetRibbonXML3 & getBackstageColumnBegin(One)  
strGetRibbonXML3 = strGetRibbonXML3 & vbTab & getGroupBegin(False, "group2", "Custom Group 2")  
strGetRibbonXML3 = strGetRibbonXML3 & getBackstagePrimaryItemBegin  
'Add custom buttons as required  
strGetRibbonXML3 = strGetRibbonXML3 & vbTab & vbTab & getButton( _   "customBMacro1", "BS Macro 1", "This is bs macro 1", "GroupSynchronizeWithSite", False)  
'Close the primaryitem element   
strGetRibbonXML3 = strGetRibbonXML3 & getBackstagePrimaryItemEnd  '
Close the group element  
strGetRibbonXML3 = strGetRibbonXML3 & vbTab & getGroupEnd  
'Close the column element  
strGetRibbonXML3 = strGetRibbonXML3 & getBackstageColumnEnd(One)  
'Open the column element  
strGetRibbonXML3 = strGetRibbonXML3 & getBackstageColumnBegin(Two)  
'Open the group element  
strGetRibbonXML3 = strGetRibbonXML3 & vbTab & getGroupBegin(False, "group3", "Custom Group 3")  
'Open the topitems element  
strGetRibbonXML3 = strGetRibbonXML3 & getBackstageTopItemsBegin  
'Add custom buttons as required 
strGetRibbonXML3 = strGetRibbonXML3 & vbTab & vbTab & getButton( "customBMacro2", "BS Macro 2", "This is bsmacro 2", "GroupViewsInfoPath", False) strGetRibbonXML3 = strGetRibbonXML3 & vbTab & vbTab & getButton( "customBMacro3", "BS Macro 3", "This is bsmacro 3", "PostReply", False)   'Close the topitems element  
strGetRibbonXML3 = strGetRibbonXML3 & getBackstageTopItemsEnd  
'Close the group element   
strGetRibbonXML3 = strGetRibbonXML3 & vbTab & getGroupEnd  
'Close the column element  
strGetRibbonXML3 = strGetRibbonXML3 & getBackstageColumnEnd(Two)  
'Close the tab element  
strGetRibbonXML3 = strGetRibbonXML3 & getTabEnd  
'Close the backstage element  
strGetRibbonXML3 = strGetRibbonXML3 & getBackstageEnd 

This produces the XML snippet:

<backstage>  
  <tab id="tab2" label="Custom Tab">  
    <firstColumn>  
      <group id="group2" label="Custom Group 2">  
        <primaryItem>  
          <button id="customBMacro1" label="BS Macro 1" supertip="This is bs macro 1" imageMso="GroupSynchronizeWithSite" onAction="OnAction"/>  
        </primaryItem>  
      </group>  
    </firstColumn>  
    <secondColumn>  
      <group id="group3" label="Custom Group 3">  
        <topItems>  
          <button id="customBMacro2" label="BS Macro 2" supertip="This is bsmacro 2" imageMso="GroupViewsInfoPath" onAction="OnAction"/>  
          <button id="customBMacro3" label="BS Macro 3" supertip="This is bsmacro 3" imageMso="PostReply" onAction="OnAction"/>  
        </topItems>  
      </group>  
    </secondColumn>  
  </tab>  
</backstage> 

The Context Menus

The second tab, named contextmenus, of the VisioControls.xlsx Excel workbook lists the possible contexts for the menus. In my example, I have used ContextMenuShape so that the button, labeled My Button, will be available on the Action Menu whenever a 2D shape is selected.

The code that creates this button can be found in getRibbon method of the Ribbon class:

 'Open the context menus group element   
strGetRibbonXML4 = getContextMenusBegin  '
Open the context menu element   
'See the contextmenus worksheet in C:\Office 2010 Developer Resources\Documents\Office2010ControlIDs\VisioControls.xlsx   strGetRibbonXML4 = strGetRibbonXML4 & getContextMenuBegin("ContextMenuShape")  
'Include any menu buttons required  
strGetRibbonXML4 = strGetRibbonXML4 & getButton( _  "customContextMacro1", "My Button", "This is my context menu macro", _  "MindMapChangeTopic", False)  '
Close the context menu element  
strGetRibbonXML4 = strGetRibbonXML4 & getContextMenuEnd  
'Close the context menus group element  
strGetRibbonXML4 = strGetRibbonXML4 & getContextMenusEnd 

This produces the XML snippet:

<contextMenus>  
  <contextMenu idMso="ContextMenuShape">  
    <button id="customContextMacro1" label="My Button" supertip="This is my context menu macro" imageMso="MindMapChangeTopic" onAction="OnAction"/>
  </contextMenu>  
</contextMenus> 

The Commands

You can disable or re-purpose built-in commands too. For example, I have provided an example of disabling the Bold button and re-purposing the Copy command …

… so that it runs some custom code:

The code that creates this button can be found in getRibbon method of the Ribbon class:

 'Open the Commands element  
strGetRibbonXML1 = getCommandsBegin  
'Add Command actions as required  
'You can disable commands  
strGetRibbonXML1 = strGetRibbonXML1 & getDisableCommand("Bold")  
'You can re-purpose commands  
strGetRibbonXML1 = strGetRibbonXML1 & getRedirectCommand("Copy")  
'Close the Commands element  
strGetRibbonXML1 = strGetRibbonXML1 & getCommandsEnd 

This produces the XML snippet:

<commands>  
  <command idMso="Bold" enabled="false"/>  
  <command idMso="Copy" onAction="CommandOnAction"/>  
</commands> 

Calling Your VBA Code

You may have noticed that the onAction attributes in all of the above XML have the value OnAction or CommandOnAction. I think that centralising the calls for the buttons and the commands like this, makes it easier to follow. I show the OnAction method below, and the CommandOnAction is very similar. So, all you have to do is ensure that you have a Case option for the ID of any control (button) that you have in the Ribbon XML.

Public Sub OnAction(ByVal control As IRibbonControl) 
' OnAction 
' 
' Abstract - This method is a callback specified in the custom UI XML file. 
' It is called by Visio when the associated button defined in the XML is pressed. 
' 
' Parameters 
' control The Ribbon UI control that was activated  
' To execute a VBA macro, use the Document.ExecuteLine method. 
 ' For example: Document.ExecuteLine("ThisDocument.HelloWorld"); 
   Select Case control.ID 
    Case "customMacro1"  
'Call to your code     
      ThisDocument.ExecuteLine "HelloWorld" Exit Sub 
    Case "customMacro2"  
'Call to your code 
    Case "customMacro3"  
'Call to your code 
    Case "customMacro4"  
'Call to your code 
    Case "customMacro5"  
'Call to your code 
    Case "customContextMacro1"  
'Call to your code 
  End Select  
MsgBox control.ID, vbInformation, "OnAction" 
End Sub

Conclusion

I hope that this provides an easy (well, not quite as easy as I would have liked) way for you to hook your VBA macros into the ribbon.

You have four different areas in the Fluent UI that you can utilise, so, have fun.

Related

Filed Under: VBA, Visio 2010

About David Parker

David Parker has 25 years' experience of providing data visualization solutions to companies around the globe. He is a Microsoft MVP and Visio expert.

Reader Interactions

Comments

  1. Adi says

    October 17, 2011 at 9:45 am

    Thank you very much for taking the time to document this but… Oh my goodness, it’s open heart surgery! How about I just pray that they fix this in the next release! Phew…

    Reply
  2. Julien says

    November 7, 2011 at 12:56 am

    Thanks for this! It has been enormously helpful for my own Visio VBA solution.

    Do you have any experience using custom icons with the technique described above? It seems I may have uncovered a bug where none of my image callbacks (loadImage or getImage) are ever being called by Visio (even after Invalidate!), leaving me high in dry in automation land.

    Any thoughts/experience with this? Thanks!
    j.

    Reply
    • davidjpp says

      November 8, 2011 at 2:21 pm

      I haven’t tried the image callback yet in VBA but this Excel blog http://www.rondebruin.nl/getimage.htm appears to have it working ok.

      Reply
  3. Bernie says

    November 9, 2011 at 2:12 am

    David, great blogs, glad I stumbled across them, this one in particular.
    I’m not sure that this entry’s results are exactly what I had hoped to achieve; I would like to associate/ deliver “trigger” code (_documentOpened, _beforeDocumentClose) to insert r remove the custom ribbon within a stencil, and would hope to only have that available if the stencil item is actually added to an open diagram, making it “one of ours”. The code to invoke, I would like to deliver via a VS2010 com addin that would be installed in the client environment. That way, only those explicitly installing and enabling the addin and further, opening and pasting an item from our macro-enabling stencil to “embed/ enable” the macro code, would see the additional ribbon elements and only in those documents for which it was valid. Reopening such a document with that pasted stencil item would automatically reopen the additional Ribbon UI elements and customizations, regardless if the stencil was open at the time or not.
    Is this viable or in line with this capability?

    Reply
    • davidjpp says

      November 9, 2011 at 8:04 am

      You are mixing a COM Addin and Macros?
      Why not do a VSTO addin for the lot?
      Have you looked at Persistent Events?
      http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=12365
      http://office.microsoft.com/en-us/visio-help/HV080351058.aspx

      Reply
      • Bernie says

        November 9, 2011 at 3:36 pm

        I had thought the vsto would be present and shown for any document, and the stencil macros would provide a per-document means of presenting the custom UI. These were initial ideas when attempting to address a complex problem with a new UI that I am still trying to understand with regards to integration with code (com/ vba). How to best address my solution, I am still formulating the approach, thus I am very thankful for your blog and for these additional links -I will look into each to see if part of my puzzle pops. I do have VS2010 for the vsto/ com addin development; I too would prefer a single point of delivery but my above perception had me thinking otherwise.
        Thank you again.

        Reply
      • Bernie says

        November 9, 2011 at 3:41 pm

        the 1st link to the 2010 sdk -the example code I followed in there to build the visio-ribbon customization test vsto had ‘dead code’ and the intent, active UI only for a specific document, does not reflect in the result because no code is set to callback to the SDK’s sample “DemoCustomUIStart/Stop” and this SDK hadn’t been updated since march ’10.
        what in the SDK were you inkling at, is there a specific section I should look into re this approach? Thanks again

        Reply
        • davidjpp says

          November 9, 2011 at 3:55 pm

          I think that you should be able to add PersistentEvents to you Stencil (I normally add it to my Template), then you can listen for the opening and closing of your stencil from your Add-in, and then modify the UI to suit.
          If you could use the PersistentEvent tool, then the Event = DocumentOpened, Target Addon = QueueMarkerEvent, Arguments = /solution=PEvtTest /cmd=1 (or similar) … you should then be able to listen for the QueueMarkerEvent

          Reply
          • Bernie says

            November 9, 2011 at 4:26 pm

            excellent- I’ll give that a try and let you know of the success. Thank you for the guidance.
            How do I “add” PersistentEvents to a stencil? you add to a template, same difference? pro/con to stencil vs. template?

          • davidjpp says

            November 9, 2011 at 4:34 pm

            I just tried adding Persistent Events to a stencil, then checked them with the following VBA code:

            For Each evt In doc.EventList
            If evt.Persistent = True Then
            Debug.Print evt.Persistable, evt.Persistent, evt.Action, evt.Event, evt.Target, evt.TargetArgs, doc.Name
            End If
            Next
            Next

            Unfortunately, opening a stencil did not fire the persistent event like it does when opening a normal document does.
            …. I’m still pondering…..

          • davidjpp says

            November 9, 2011 at 4:52 pm

            Public Sub StartListening()
            Set mapp = Visio.Application
            End Sub

            Public Sub StopListening()
            Set mapp = Nothing
            End Sub

            Private Sub mapp_BeforeDocumentClose(ByVal Doc As IVDocument)
            If Doc.DocumentSheet.CellExists(“User.MySpecialStencil”, Visio.VisExistsFlags.visExistsAnywhere) Then
            Debug.Print Doc.Name, “closed”
            End If
            End Sub
            okay, my thoughts are that your addin should listen to the Application DocumentOpened and BeforeDocumentClosed events, and add a user cell into the documentsheet.
            Then you can check for the presence of this User cell when ever a document is opened or closed.
            The following is VBA, but you should use AddAvise with vb.net or just Add with C# :

            Dim WithEvents mapp As Visio.Application

            Private Sub mapp_DocumentOpened(ByVal Doc As IVDocument)
            If Doc.DocumentSheet.CellExists(“User.MySpecialStencil”, Visio.VisExistsFlags.visExistsAnywhere) Then
            Debug.Print Doc.Name, “opened”
            End If
            End Sub

          • Bernie says

            November 9, 2011 at 4:59 pm

            thanks David, I had found the SDK tool as you replied… the above code will help greatly, along the same lines I had thought, where dropping a stencil-specific item into the document would ‘validate’ it as customUI using doc (you mention user cell above),

  4. Bernie says

    November 9, 2011 at 4:51 pm

    I found in the VB macro editor, in the “this document” codepage, the attribute/ property PersistsEvents. I am guessing I set this to True. I have not found what you allude to as the “PersistentEvent tool”… still looking.

    Reply
    • davidjpp says

      November 9, 2011 at 4:54 pm

      When you install the SDK, you will get an extra group SDK Tools on the Devloper tab (assuming that you have found the Run in Developer mode switch in the File \ Options \ Advanced )

      Reply
      • brrrknee says

        November 14, 2011 at 3:11 am

        David, of the 3 tools, only the “event monitor” starts, the Persistent Events and Print Shapesheet tools do nothing. macro recording doesn’t capture clicks in the ribbon or its commands either. what might be conflicting on my environment?
        I’m just trying to find a way to simply -as commandbuttons/ commandbars were -locate and ‘click’ the orgchart “relayout” and a few other org chart buttons from my VBA code. I cannot believe the dearth of info re the programmatic access to the ribbon, but there are plenty of examples to customize it. I see one example where someone is forced to use the MS IAccessible interface of oleacc.dll; why is such a simple task taken to such an excruciating level of complexity to perform in the new UI? What am I missing here?
        Thank you for the assistance.

        Reply
        • davidjpp says

          November 14, 2011 at 9:21 am

          I had a problem recently where my Persistent Events and Print SHapeSheet tools were not working either … I had installed the 64bit version of the SDK accidently, and installing the 32bit version fixed that.

          I found this blog article – http://www.wordarticles.com/Shorts/RibbonVBA/RibbonVBADemo.php which has code to give you access to the Ribbon from VBA – the only change I had to do in Visio was to insert Application. in front of CommandBars(“Ribbon”).

          As far as running the Org Chart addon from VBA … I guess you could if you knew the arguments for each command.

          Reply
          • brrrknee says

            November 17, 2011 at 11:18 pm

            David, I am not “running the Org Chart addon” from VBA, but navigating the org chart Command Bar/ Buttons to apply layouts and relayout after resizing the elements. very simple with command bars and buttons, 5-10 lines, no need to know any APIs. However, now it seems to “navigate to and press” an org chart button, I have to write large amounts of code in C/C++ to use the newer MS UI Automation (or the many lines of VBA code referenced to use MSAA IAccessible). I find no VB support for this newer accessibility interface, MS stating that UIA will replace the MSAA IAccessible interface. Not having access to the accessibility interface from the Office support VBA is difficult to grasp for rationale. The example code you link to above, is a VBA use of the “decade old (MS’ description to steer folks to the UIA)” MSAA IAccessible interface, and I may have to just go with that MSAA for the near term. I had looked at that example before, but was hunting for a VBA implementation of the UIA ‘newer’ technology. Apparently MS is not looking to support its office VBA products in this fashion. Thank you for your help, I am much better informed through you!

  5. Bernie says

    November 9, 2011 at 4:54 pm

    ahhh, in the SDK… 🙂

    Reply
  6. brrrknee says

    November 19, 2011 at 6:39 am

    I’m running 64b office on a 64b system w win7 64b. therefore I loaded the 64b SDK; it isn’t working as noted above; does the SDK have a 32b limitation for those 2 tools?

    Reply
  7. brrrknee says

    November 19, 2011 at 6:44 am

    David, just noticed in the active add-on tab, the ‘working’ active add-on “monitor events” is an .exe, while the other two active ‘non responsive’ add-ons “Print Shape Sheet…” and Persistent Events…” are both .VSLs is there a setting I might have turned off disabling VSLs?

    Reply
  8. Shaul says

    November 20, 2011 at 7:07 pm

    Hi David,
    Great post!

    I can’t download your example, maybe you can re-upload it?

    Thanks in advance
    Shaul

    Reply
  9. musoitank says

    December 3, 2011 at 10:50 pm

    Please re-upload the .vsd example – someone?

    Reply
  10. frankki says

    January 12, 2012 at 3:19 pm

    I really love this (working!) sample, but I struggle in getting the split button large.
    Could it be that you forgot a variable for that or is it me just being blind?
    Thanks for a short advise

    Reply
    • davidjpp says

      January 31, 2012 at 11:39 am

      size=”large” ?

      Reply
    • brrrknee says

      January 31, 2012 at 5:01 pm

      moreover, this example is written off of stubs of the old interface, and nowhere is there a pure example written using the new test/automation UI. why cannot the MS/ MVP teams see that stating the new UI is the way of the future development would make using such old-form examples a wary step for us? We still need to access buttons and commands. HOW DO WE DO IT using purely the new test/automation approach and not have to rely upon past techniques?

      Reply
      • davidjpp says

        January 31, 2012 at 10:44 pm

        MVPs are not a team … we are all independent (and unpaid) Visio enthusiasts.
        I’m not sure what you are saying?
        If you are building a system that needs to be subjected to a test harness, then you need to have separation of concerns.
        All of the UI elements should be distinct from any calls that you make, thus you should be able to test the calls directly, without simulating clicking or selecting any UI elements.
        This is one of the reasons why I like to use the MVVM model with WPF … even within Visio add-ins.
        Hooking in the Ribbon within a VIsio add-in is far easier than the VBA code that I offered, but I recognise that some people want to use the ribbon with VBA too.

        Reply
        • brrrknee says

          January 31, 2012 at 11:17 pm

          I understand that the MVPs are not ‘a team’ that was my mistake in this description.
          I don’t want to have to do any of this, but since I had a simple command-bar /button access in a prior, very important, macro. now it doesn’t work in ribbon interfaces, so rather than the few lines of code that had previously worked, I am now wrestling with all of this workaround to simply “find the button and click it” from within the macro vba has become quite frustrating, and examples of UIA to do this ‘find the button and click it’ vs. the ribbon, I have yet to find. Your forum is great, I am merely frustrated with the blind MS push to the ribbon and the UIA with apparent disregard to the impact of simple business users.

          Reply
          • davidjpp says

            February 1, 2012 at 6:09 am

            I actually agree with you about that. It is really disappointing that there is not a simple way to add a button to the Ribbon to run a VBA macro in Visio. It is something that several of us MVPs have complained to Microsoft about. My code was aimed at providing a way to create/remove buttons when the document opens/closes. My fellow MVP, Chris Roth aka VisGuy, has responded to me as follows:

            Ok, I found a simpler way after hacking a bit.

            1. Create a custom tab, group, etc.
            2. Export the custom UI
            3. Edit it in notepad to call your macro

            The trick is to add or edit the onAction xml, which I learned from David’s article. Here I’ve set it to ThisDocument.DoStuff.

            You can now import this Ribbon UI. If the VBA macro is present, it will run. If not, it won’t but the button will still be there.

          • brrrknee says

            February 1, 2012 at 6:26 am

            even simpler: take an existing, in fact pre-existing commandbar /buttons, the OrgChart Wizard. I do not want to reinvent the wheel, I just look up the commandbar that ‘is’ the wizard (almost always found at cb index 100 or 101) and select its ‘relayout’ button. no new commands or buttons. just “find org chart stuff” select and execute “relayout”. a handful of lines of code pre-ribbon; all ribbon-influenced examples, though not addressing this locate-subject but a build-it custom focus, are many many pages of code that obfuscate the simple request: locate and execute a known-to-exist command. now I am confounded in finding MSAA (the “old” UI accessibility) and/or UIA (the “new” and to replace MSAA UI accessibility) means of finding the reshuffled needles in the haystack called the ribbon. I’d also rather code to the UIA to obviate any need to rewrite after MSAA methods are tossed aside like commandbars… it happened once, it’ll happen again.
            David, I do appreciate your feedback and ideas, thank you, I hope to be able to read more of your blogs and of your partners’.

  11. brrrknee says

    February 6, 2012 at 10:48 pm

    Working through several differing samples, I’ve noticed some things that you likely can clarify:

    When I add “oleacc.dll” as a resource to my visio 2010 VBA reference list(the library that implements IAccessible according to MS, etc.), the exposed interfaces (within VBA IDE for oleacc.dll) do not include IAccessible.
    While code that uses the IAccessible such as x.accName and x.accParent seem to be working, I am hitting several cases where the IAccessible element has no name where I believe it should, (perhaps it is a IDispatch object?) but cannot find the means to view the objects.

    Also, one sample I have found helpful uses the x.accNavigate method to get to “FirstChild” of an IAccessible element. MS on 9/7/11 posted a statement (perhaps earlier) that .accNavigate is deprecated and will trigger an error. No suggestions online other than “use other methods”… it is my understanding that this call is essentially “getChildren” and then referencing the top/first of that list; am I close? If not how(which .accXxxx methods) can I achieve the “firstChild” nav utility?
    If I could ‘see’ the object via the IDE it would help me here, but as noted at top, the VBA IDE is not edit-or-view aware of IAccessible methods and properties, though the compiled code seems to be… perplexing.
    Thanks David!

    Reply
  12. spols says

    April 2, 2012 at 12:49 am

    Great article.
    However, I can’t seem to collect the sample vsd download – skydrive.live.com returns: “An error has occurred. Please try again.”

    Reply
    • davidjpp says

      April 11, 2012 at 1:59 pm

      I have refreshed the link for you to try again…

      Reply
  13. Kedas says

    April 27, 2012 at 11:06 am

    This requires ‘IRibbonControl’ as parameter -> Public Sub OnAction(ByVal control As IRibbonControl) in VBA
    Is there a way you call a function in the add-in and then this function calls a macro like Sub Refresh() ?

    This to stay compatible with existing documents (from templates) with existing macros.
    I can change the templates but not all the documents.

    Thanks

    Reply
  14. Prasanna says

    May 24, 2012 at 4:28 pm

    David,
    Thanks for the help on this topic.
    I had a couple of issues; The Macro 1,2,3,4 buttons only execute the code once.
    For example, while debugging, if I stop the code, make changes to my custom macro and click again, it won’t work.
    I have to restart Visio again for that button to work.
    Also, if I only close the Visio sheet (and not Visio program), and reload the sheet, I have two ribbon tabs of the same name instead of the single “Custom Ribbon” tab.
    Any clue as why this may be happening.

    Reply
    • davidjpp says

      May 28, 2012 at 9:58 pm

      Are you running the code in a drawing or a stencil ?
      You should run UnloadRibbon() before editing, then LoadRibbon() when you have finished editing your macros

      Reply
  15. francisco says

    October 9, 2012 at 5:51 pm

    I’ve tried to build “two groups” usiing “begin and end group functions” but it doesn’t works. Aparentilly the xml is correct, comparing with others xml in microsoft website. Do you know the probable cause?

    Reply
    • Gilles says

      January 15, 2015 at 11:17 am

      Hi, I had exactly the same issue as Francisco:

      If includeContextMenus Then
      ‘Open the context menus group element
      strGetRibbonXML4 = getContextMenusBegin
      ‘Open the context menu element
      ‘See the contextmenus worksheet in C:\Data\Perso\Toolbox\@Visio\Macros\VisioControls.xlsx

      strGetRibbonXML4 = strGetRibbonXML4 & getContextMenuBegin(“ContextMenuShape”)
      ‘Include any menu buttons required
      strGetRibbonXML4 = strGetRibbonXML4 & getButton( _
      “SelectSimilarShapesByMaster”, “Select Shapes with same Master”, “Select all Shapes which descend from the same Master”, _
      “SourceControlShowHistory”, False)
      ‘Close the context menu element
      strGetRibbonXML4 = strGetRibbonXML4 & getContextMenuEnd

      ‘Open the context menu element
      strGetRibbonXML4 = strGetRibbonXML4 & getContextMenuBegin(“ContextMenuShape1D”)
      ‘Include any menu buttons required
      strGetRibbonXML4 = strGetRibbonXML4 & getButton( _
      “SelectSimilarShapesByMaster”, “Select Shapes with same Master”, “Select all Shapes which descend from the same Master”, _
      “SourceControlShowHistory”, False)
      ‘Close the context menu element
      strGetRibbonXML4 = strGetRibbonXML4 & getContextMenuEnd

      ‘Close the context menus group element
      strGetRibbonXML4 = strGetRibbonXML4 & getContextMenusEnd

      strGetRibbonXML = strGetRibbonXML & strGetRibbonXML4
      End If

      does not work, even if each the xml code seems to be correct.

      If I try to add the menus individually it works.
      If I create two “getContextMenusBegin / getContextMenusEnd” blocks, only the last works.

      But I do not manage to have both menus working.

      Can somebody help?

      Reply
  16. Roman says

    January 17, 2013 at 3:58 pm

    francisco, did you find a solution? I am having the same trouble.

    Reply
  17. Thomas says

    July 23, 2013 at 12:44 pm

    Thanks for this excellent tutorial.
    I added a checkbox to your demo and want to initialize its state with a getPressed callback.
    But this is never called.
    Same problem with getLabel while onAction and onLoad are working properly.
    Please find more information here:
    http://visguy.com/vgforum/index.php?topic=4954.0
    Any idea?

    Thanks,
    Thomas

    Reply
    • davidjpp says

      July 23, 2013 at 4:06 pm

      Hmmm, the following thread is not filling me with great hope : http://social.microsoft.com/Forums/ar-SA/988b3569-8519-4253-b8a9-222740c473d8/problems-with-vba-ribbon-customization-in-project-2010-pro

      Reply
      • Thomas says

        July 23, 2013 at 10:07 pm

        Thanks, David.
        Really sad, that Visio still behaves so different to other Office products…
        The method, described in your link would be OK for me.
        But unfortunately there is no “pressed” attribute defined, as it is for other callbacks (getLabel => label).

        Reply
    • Thomas says

      July 26, 2013 at 10:47 pm

      Solved.
      The function declaration must be:
      Public Function Checkbox_getPressed(control As IRibbonControl) As Boolean

      Reply
  18. Martin says

    October 3, 2013 at 12:42 pm

    David,
    Great article, thanks a lot. I’m not sure on how I can have this ribbon extension to appear in visio on all times. I have a solution in mind like a Word Template placed in the Auto-Start folder of Word which contains the UI extension and will be loaded on every start of Word.
    Can you guid me in the right direction maybe with even a runable sample?
    Thanks so much for your help.
    Martin

    Reply
    • davidjpp says

      March 26, 2014 at 3:58 pm

      Visio does not have a personal macros file that is opened automatically.
      Of course, you could write an add-in …

      Reply
  19. RichZ says

    April 3, 2014 at 2:07 am

    So, I’m still modifying my code… but I seem to have the same problem that someone else reported. For whatever reason, the buttons on the ribbon will only run my macro once. Currently I am just testing, so I’ve placed your code within the VSD document, but my macros are stored in a VSS; the stencil of course opens upon DocumentOpen, so that should not be the issue.

    I can only imagine that there is some issue with having this code stored in the local document, but calling a macro in a stencil file?

    Reply
    • RichZ says

      April 3, 2014 at 2:24 am

      Hmm..; well I tested my previous theory and this is not the case. I placed the macros local to the VSD document, and the results are the same; the buttons I’ve added to the ribbon stop working after I click any of the buttons once. Very odd.

      Reply
  20. RichZ says

    April 5, 2014 at 8:52 pm

    okay, I’ve narrowed down the issue. It seems that the macros I’ve added to the custom ribbon work until I call a macro that drops a stencil on the page that has an activex textbox inside of it. I’m not sure why this breaks ribbon. I’ve tried doing this using the code you have shared with us here, and also by using the example provided by Microsoft in the SDK. If anyone has any thoughts on this then I would greatly appreciate any advice you may have.

    Reply
    • davidjpp says

      April 8, 2014 at 3:29 pm

      Does VBA Editor / Debug / Compile still process OK ?

      Reply
  21. Stephen says

    November 25, 2014 at 3:14 am

    Can the methods developed here also be used in Excel?

    Reply
    • davidjpp says

      December 26, 2015 at 11:48 am

      Possibly, but I find that creating a proper ribbon with a VSTO app to be the best solution in most cases.

      Reply
  22. James says

    June 2, 2021 at 12:04 am

    Very nice.

    Was wondering if it is possible to put the custom group into an exsiting Tab?

    Eg. Create a group called ‘Custom’ and place it in the default Home group.

    Reply
    • David Parker says

      June 2, 2021 at 11:00 am

      Certainly you can!
      Open the Ribbon class and find the line:
      strGetRibbonXML2 = strGetRibbonXML2 & getTabBegin(False, “tab1”, “Custom Ribbon Tab”)
      and replace it with:
      strGetRibbonXML2 = strGetRibbonXML2 & getTabBegin(True, “TabHome”, “Home”)

      Generally I don’t like putting any macros in diagram documents, so I will write an article about how put all the code into a stencil, then it can be used on many diagrams.

      Reply
      • David Parker says

        June 2, 2021 at 12:35 pm

        Okay, here is the article Adding Macro Ribbon Buttons to Visio Documents-from-a-stencil/

        Reply
        • Dmitry says

          August 12, 2021 at 10:58 am

          Thank you! This article is very useful!

          Reply
  23. Marco says

    November 28, 2023 at 2:29 pm

    This is great news! I’m trying to do some coding on my Visio Drawings and find this extremely helpful! Sadly, I couldn’t download your VSD file, perhaps the link changed?

    Thanks for this excellent article!

    Reply
    • David Parker says

      November 29, 2023 at 1:03 am

      I have updated thee link 🙂

      Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Primary Sidebar

  • LinkedIn
  • Twitter

Recent Posts

  • Fixing dimensions of 2D shapes
  • Merging Linked Data from Similar Tables
  • Smart Radio Buttons and Check Boxes in Visio
  • Using Button Face Ids in Visio
  • Grid Snapping Revisited

Categories

Tags

Accessibility Add-Ins Connectors Containers Data Export Data Graphics Data Import Data Visualizer Educational Excel GraphDatabase Hyperlinks Icon Sets JavaScript LayerManager Layers Legend Link Data to Shapes Lists MSIgnite MVP Office365 Org Chart PowerApps PowerBI PowerQuery Processes Setup and Deployment Shape Data Shape Design ShapeSheet ShapeSheet Functions SharePoint 2013 SQL Teams Validation VBA Video Visio Visio 2007 Visio for the Web Visio Online Visio Services Visio Viewer Webinar

Footer

bVisual Profile

The UK-based independent Visio consultancy with a worldwide reach. We have over 25 years experience of providing data visualization solutions to companies around the globe.

Learn more about bVisual

  • Amazon
  • E-mail
  • Facebook
  • LinkedIn
  • Twitter
  • YouTube

Search this website

Recent posts

  • Fixing dimensions of 2D shapes
  • Merging Linked Data from Similar Tables
  • Smart Radio Buttons and Check Boxes in Visio
  • Using Button Face Ids in Visio
  • Grid Snapping Revisited

Copyright © 2025 · Executive Pro on Genesis Framework · WordPress · Log in