Visio Guy

Visio Guy Website & General Stuff => User-submitted Stuff => Topic started by: Thomas Winkel on March 28, 2016, 03:34:22 PM

Title: Custom Ribbon with VBA in Visio Stencil
Post by: Thomas Winkel on March 28, 2016, 03:34:22 PM
Hi,

please find attached a stencil that will draw a custom Ribbon "Visio-Tools" on load.
The XML code that defines the Ribbon is stored in the stencils document ShapeSheet "User.Ribbon".
You can export, modify and import the XML code with a mouse click.
The Ribbon will refresh automatically, no restart required.

User settings (XMLPath and reloadOnImport) are stored in the Windows Registry.
There is a button to remove this Registry settings.

The code has been derived from here:
http://blog.bvisual.net/2011/03/14/how-to-run-vba-macros-from-a-ribbon-button-in-visio-2010/
But it is much more comfortable to create the XML in your favorite editor (in my case Notepad++) than with code.

Feel free to use this stencil as start-up for your own projects.
Please give feedback if there is something to improve.

Regards,
Thomas
Title: Re: Custom Ribbon with VBA in Visio Stencil
Post by: phillip_141 on July 29, 2016, 05:36:37 PM
How can I view the shapsheet of the stencil? I figured it would be the same as  viewing it for a document, but the entire shape  design section of the developer ribbon is greyed out when I open just the stencil. The reason I ask is because I wanted to add this code to an existing stencil I use, but kept getting xml import errors. I can get the original "Visio tools" file to accept the xml file I have edited, but my stencil hits an error at this line:

ThisDocument.DocumentSheet.Cells("User.Ribbon").FormulaU = Chr(34) & XML & Chr(34)

which is from the "importXML()" sub.

Any help you could provide would be awesome.
Title: Re: Custom Ribbon with VBA in Visio Stencil
Post by: Thomas Winkel on July 29, 2016, 06:23:22 PM
Hi,

the problem is, that the code tries to access an user cell "User.Ribbon" that does not exist in your stencil.
So you have to create it by hand:
* Right click on stencil: Edit Stencil
* Right click on stencil: Drawing Explorer Window
* Right click on root in Drawing Explorer Window: Show ShapeSheet
* Right click in ShapeSheet: Insert Section -> User defined cells

Here is a video:
https://youtu.be/hzWDNw9dz8k

Regards,
Thomas
Title: Re: Custom Ribbon with VBA in Visio Stencil
Post by: phillip_141 on August 04, 2016, 03:54:00 PM
Ah I see. Thank you! I'm sure I can make use of this in the future! Nice ribbon code by the way. Managed to make lots of changes and expand the ribbon to suit my needs. I appreciate your assistance!
Title: Re: Custom Ribbon with VBA in Visio Stencil
Post by: kedas on October 30, 2017, 11:35:20 AM
Hi,

is it possible to call macros inside the open document from the vss ribbon button?
I like to update the ribbon by opening a vss after opening a document but I can't seem to call subs from that document.

Thanks
Title: Re: Custom Ribbon with VBA in Visio Stencil
Post by: kedas on October 31, 2017, 05:31:20 PM
I have this file attached, the macros don't fire (macros are just msgbox now to see if it works)
When pressing Ctrl+Shift+C it will change the Ribbon, only my 2 buttons.
When pressing Ctrl+Shift+R it will reset the Ribbon with my 2 extra butons

Do you know why they don't work??
I basically used the code of the stencil example but put it in a .vsd file (I don't use set CustomUI close reopen)

edit, found it i thought you could choose the name 'Button_OnAction'
Title: Re: Custom Ribbon with VBA in Visio Stencil
Post by: DJHarris71 on February 02, 2018, 01:24:36 PM
Hello,
I know this is post is a bit old, but this is the solution I have been looking for!  Thanks very much!
I did make mine a bit simpler and chose to create a string in VBA for the XML, and got rid of all the subs that move the string in and out of the shape data.  It works very well.


    ribbonXML = "<customUI onLoad=""OnRibbonLoad"" xmlns=""http://schemas.microsoft.com/office/2009/07/customui"">"
    ribbonXML = ribbonXML + "   <ribbon>"
    ribbonXML = ribbonXML + "       <tabs>"
    ribbonXML = ribbonXML + "           <tab id=""Tab1"" label=""Tab1"">"
    ribbonXML = ribbonXML + "               <group id=""Group1"" label=""Group1"" >"
    ribbonXML = ribbonXML + "                   <button id=""Button1"" label=""Button1"" supertip=""Button1"" size=""large"" imageMso=""MailMergeGoToNextRecord"" onAction=""Button_OnAction""/>"
    ribbonXML = ribbonXML + "                   <button id=""Button2"" label=""Button2"" supertip=""Button2"" size=""large"" imageMso=""SignaturesLoading"" onAction=""Button_OnAction""/>"
    ribbonXML = ribbonXML + "               </group>"
    ribbonXML = ribbonXML + "           </tab>"
    ribbonXML = ribbonXML + "       </tabs>"
    ribbonXML = ribbonXML + "   </ribbon>"
    ribbonXML = ribbonXML + "</customUI>"


However - it seems anytime I try to do something not provided in your example, my ribbon will not load.  Here are the three things I tried:
1) adding getVisible=""getVisible"" to the tabs and groups. 
2) adding getEnabled=""getEnabled"" to the tabs and groups. 
3) adding an editBox

All the above use the standard method (add the action in the ribbon with the callback sub name, add the callback sub) as shown below:


{the gobal variable}
Public objRibbonVisible As Boolean
'
{inside the ribbon string}
ribbonXML = ribbonXML + "               <group id=""Group1"" label=""Group1"" getVisible=""GetVisible"">"

{The callback sub}
Public Sub GetVisible(control As IRibbonControl, visible)
    visible = objRibbonVisible
    objRibbon.Invalidate
End Sub

Is there something I am missing??
Title: Re: Custom Ribbon with VBA in Visio Stencil
Post by: perry59 on March 15, 2020, 06:50:52 PM
I know this is an old thread, but hope I can still get an answer.
I'm new to this ribbon (been on visio 2007 until just this year) stuff but found this stencil pretty cool and modified it to suite my needs pretty easily.
the only thing I can't get it to do is use different icons for the buttons.
there are lines in the xml file like this imageMso="SomeIcon" which specify an image but if I change that to any of the other icons which are in the word document that contains them, no image shows up.
What am I doing wrong? does this xml code actually access that word document on microsoft's site each time it loads? that doesn't sound very efficient, and what if you have no internet connection?
Thanks for any help
Title: Re: Custom Ribbon with VBA in Visio Stencil
Post by: AndyW on March 16, 2020, 11:01:17 AM
Handle the following to load your image,

Public Function LoadImage(strImageName As String) As IPictureDisp
Title: Re: Custom Ribbon with VBA in Visio Stencil
Post by: perry59 on March 21, 2020, 06:37:51 PM
Quote from: AndyW on March 16, 2020, 11:01:17 AM
Handle the following to load your image,

Public Function LoadImage(strImageName As String) As IPictureDisp

I don't see any code at all like that in the current stencil but it loads images just fine.
Title: Re: Custom Ribbon with VBA in Visio Stencil
Post by: Remko on November 29, 2022, 04:58:35 PM
HI, I get a permission denied trying to export the XML.  or do you need to supply one first? was hoping to export one so i can look and learn from it.
Title: Re: Custom Ribbon with VBA in Visio Stencil
Post by: Thomas Winkel on December 08, 2022, 09:58:57 AM
Hi,

try to set the xml path to something like c:\temp\ribbon.xml (c:\temp must exist).
c:\ribbon.xml give me the same permission denied message.

Suggested proceeding is:

The existing buttons demonstrates:
* Ribbon xml for Buttons, menus, checkboxes, splitter
* Store settings in Windows Registry
This is only to give you a starting point.
For real projects I suggest to remove these buttons and handle the xml import / export from VBA editor.
Title: Re: Custom Ribbon with VBA in Visio Stencil
Post by: Nikolay on December 08, 2022, 03:01:04 PM
Quote from: Remko on November 29, 2022, 04:58:35 PM
HI, I get a permission denied trying to export the XML.  or do you need to supply one first? was hoping to export one so i can look and learn from it.

Yes, you need to supply one first.
There is nothing to export in "stock" Visio. You'll get an empty string as output.
I.e. everything that you provide in ribbon.xml is applied "on the top" of the Visio's built-in user interface.
By default, nothing is applied, so the ribbon you export will be empty.
Title: Re: Custom Ribbon with VBA in Visio Stencil
Post by: Thomas Winkel on December 08, 2022, 05:39:28 PM
Hi Nikolay,

I guess Remkos question is about the "Export XML" function of my Visio-Tools stencil from the first post.
This will export the XML that defines the Visio-Tools ribbon (see attached screenshot).
The XML string is stored in the stencils document property User.Ribbon.

BR,
Thomas
Title: Re: Custom Ribbon with VBA in Visio Stencil
Post by: Nikolay on December 08, 2022, 05:44:21 PM
I see. Thank you for the clarification. I thought it was about exporting the built-in ribbon
Title: Re: Custom Ribbon with VBA in Visio Stencil
Post by: Remko on December 13, 2022, 09:52:30 AM
thank you guys for your replies. the thing that gave me permission errors was because i didnt declare a filename + extension.

i put this in the Set XML Path window: c:\temp\ 
I should have put: c:\temp\ribbon.xml   :)
Title: Re: Custom Ribbon with VBA in Visio Stencil
Post by: Remko on December 13, 2022, 11:43:47 AM
im sorry for being so VBA clueless, All i need is a example VBA so i can figure out how to bind a button to a macro.

I added these 2 buttons to the Ribbon XML

<separator id="separator" />
<button id="customMacro1" label="delete all guides" supertip="Delete all guides" size="large" imageMso="_3" onAction="Button_OnAction"/>
<button id="customMacro2" label="A3 guides" supertip="A3 guides" size="large" imageMso="_2" onAction="Button_OnAction"/>


but cant make them execute.

I have a class module containing this:

Public Sub Class_Initialize()

' Class_Initialize
'
' Abstract - This constructor is intentionally left blank.

    ' No initialization is required.
End Sub
Public Function IRibbonExtensibility_GetCustomUI(ByVal RibbonID As String) As String

' IRibbonExtensibility_GetCustomUI
'
' Abstract - This method is a callback that is called by Visio to obtain the
' custom UI definition.
'
' Parameters
' RibbonID         A string identifying the Visio UI
'
' Return Value     A string representing the XML defining the custom UI

    IRibbonExtensibility_GetCustomUI = getRibbonXML(True, True, True, True)
End Function

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 "Macro1"
            Exit Sub
        Case "customMacro2"
            ThisDocument.ExecuteLine "deleteallguides"
             Exit Sub
            'Call to your codedeleteallguides
        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
Public Sub CommandOnAction(ByVal control As IRibbonControl, _
    ByVal cancelDefault As Boolean)

' CommandOnAction
'
' Abstract - This method is a callback specified in the custom UI XML file.
' It is called by Visio when the associated repurposed Ribbon control is used.
'
' Parameters
' control           The Ribbon UI control that was activated
' cancelDefault     If true, call the built-in command after the custom code
' is complete

    ' Do custom work when the Copy button is pressed, for example.
    Select Case control.ID
        Case "customMacro1"
            'Call to your code
        Case "customMacro2"
            'Call to your code
        Case "customMacro3"
            'Call to your code
    End Select
    MsgBox control.ID, vbInformation, "CommandOnAction"
    cancelDefault = False
End Sub


and a normal module with the macros:
Public Sub Macro1()

    'Enable diagram services
    Dim DiagramServices As Integer
    DiagramServices = ActiveDocument.DiagramServicesEnabled
    ActiveDocument.DiagramServicesEnabled = visServiceVersion140 + visServiceVersion150

    Application.ActiveWindow.Page.AddGuide visVert, 3.937008, 11.811024

    Application.ActiveWindow.SetViewRect -20.710301, 27.271981, 56.799539, 47.81824

    Application.ActiveWindow.SetViewRect -7.666805, 17.177788, 28.698716, 24.160797

    Application.ActiveWindow.SetViewRect -4.472441, 14.708662, 21.811024, 18.362205

    Application.ActiveWindow.SetViewRect -3.4027, 13.863892, 19.474128, 16.394825

    Application.ActiveWindow.Page.AddGuide visVert, 6.496063, 7.283464

    Application.ActiveWindow.Page.AddGuide visHorz, 5.511811, 10.03937

    Application.ActiveWindow.Page.AddGuide visHorz, 5.11811, 4.330709

    'Restore diagram services
    ActiveDocument.DiagramServicesEnabled = DiagramServices

End Sub
Public Sub deleteallguides()

    'Enable diagram services
    Dim DiagramServices As Integer
    DiagramServices = ActiveDocument.DiagramServicesEnabled
    ActiveDocument.DiagramServicesEnabled = visServiceVersion140 + visServiceVersion150

    Dim vsoSelection1 As Visio.Selection
    Set vsoSelection1 = Application.ActiveWindow.Page.CreateSelection(visSelTypeByType, visSelModeSkipSuper, visTypeSelGuide)
    Application.ActiveWindow.Selection = vsoSelection1

'    ActiveWindow.DeselectAll
'    ActiveWindow.Select Application.ActiveWindow.Page.Shapes.ItemFromID(148), visSelect
'    ActiveWindow.Select Application.ActiveWindow.Page.Shapes.ItemFromID(150), visSelect
'    ActiveWindow.Select Application.ActiveWindow.Page.Shapes.ItemFromID(151), visSelect
'    ActiveWindow.Select Application.ActiveWindow.Page.Shapes.ItemFromID(152), visSelect
    Application.ActiveWindow.Selection.DeleteEx (visDeleteNormal)

    'Restore diagram services
    ActiveDocument.DiagramServicesEnabled = DiagramServices

End Sub


thank you for your time.
Title: Re: Custom Ribbon with VBA in Visio Stencil
Post by: Thomas Winkel on December 14, 2022, 09:37:27 AM
Please attach your modified stencil, then I will investigate this.
Title: Re: Custom Ribbon with VBA in Visio Stencil
Post by: Remko on December 14, 2022, 11:33:12 AM
I created marcos in the file. not the stencil, and its a mess :) thats why i prefer a "simple" example VBA snip. I attached the file..  thank you for your time.
Title: Re: Custom Ribbon with VBA in Visio Stencil
Post by: Thomas Winkel on December 14, 2022, 02:37:32 PM
I recommend to keep all code only in the stencil, not in documents.
It's easier to maintain code in a global stencil than hundreds of documents.

See attached stencil.
Title: Re: Custom Ribbon with VBA in Visio Stencil
Post by: Remko on December 15, 2022, 04:50:03 PM
Hi Thoman, many thanks for this. I will hopefully have some time tomorrow to play around with this, but is does give me some better insight.

Q: Does adding this stencil to your visio drawing mean you are actually running macros in a non macro enabled visio file?

Q2: after editing VBA in the stencil, I cant save because its read only, is this normal stencil behavior?
Title: Re: Custom Ribbon with VBA in Visio Stencil
Post by: Thomas Winkel on December 15, 2022, 07:07:21 PM
Q1:
The macros are running from the stencil.
No need to enable macros for the document.
With the Visio Object model you can directly access everything within the current application:

This example prints the same result to Immediate window, regardless if running from document or stencil:

Option Explicit 'Always use "Option Exlicit"

Sub IterateThroughAllShapesWithinCurrentVisioApplication()
    Dim doc As Visio.Document
    Dim pge As Visio.Page
    Dim shp As Visio.Shape
   
    'Never use this (except you really know what you are doing):
    'On Error Resume Next
   
    For Each doc In Application.Documents
        Debug.Print "* " & doc.Name
        For Each pge In doc.Pages
            Debug.Print "....* " & pge.Name
            For Each shp In pge.Shapes
                Debug.Print "........* " & shp.Name
            Next shp
        Next pge
    Next doc
End Sub


Btw. Visio Documents, Stencils & Templates are the exactly same object types: Visio.Document
Only the filename extension differs and tells Visio how to handle it.

Q2:
Before you edit a stencil you should set it to "Edit" mode via context menu (see attached screenshot).
Before adding master shapes this is mandatory, but before editing code it's easy to forget.

Extra tip:
In the VBA editor, goto Tools -> Options...
Uncheck "Auto Syntax Check"
Check "Require Variable Declaration"
(See second screenshot)
Title: Re: Custom Ribbon with VBA in Visio Stencil
Post by: bossi on January 02, 2023, 12:46:18 AM
happy new one folks.
So i dropped the "VisioTools" into "MyShapes" and activated it in the "Shapes" Section, but there is no further happening.
Is there supposed to appear an additional Tab entry or sth ?

Edit:
ok , security Setting was on , had to either enable macros or better apply own certificate to it .