So I have a custom ribbon that looks something like
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="RibbonLoadFunc" >
and a function
Private Sub RibbonLoadFunc(Ribbon As IRibbonUI)
MsgBox "Hello World"
End Sub
So when I open the document, it prints "Hello World" on the screen as expected. Now, my question is since a reference to IRibbonUI is passed into the function, can I get values of fields of underlying elements? Since the ribbon is defined as an XML document, I would imagine I should be able to access all elements within said document. So, for instance, if I also had
<tab id="myTab">
<group id="myGroup">
<button id="myButton" onAction="someAction" label="someLabel"/>
</group>
</tab>
Is there a way to print the label of myButton, "someLabel", instead of "Hello World"?
Alternatively, is there a way to pass constants into the onLoad function of a IRibbonUI?
This question borders on being too broad and you'd really need to do some extensive research on working with Ribbon XML. Microsoft has done a pretty good job of hiding its documentation since the release of the new JS APIs, so I compiled a list of links and posted it in the MSDN forums: https://social.msdn.microsoft.com/Forums/office/en-US/ba8c9d0b-7312-4503-8167-f2ef86f17435/information-on-the-office-fluent-ui-ribbon-for-developers?forum=officegeneral. I recommend you start with the 3-part series on "Customizing the Office 2007 Fluent UI for developers".
In a nutshell, though, the Ribbon UI interacts with code via "callbacks" - all interaction must be started by the Ribbon, itself. There's no way to "query" the Ribbon object and its controls as you're accustomed to doing using VBA. The VSTO extensions do provide this, as long as the Ribbon you want only requires things supported by its Ribbon Designer. But in the background that works more or less the way I describe below.
Your RibbonLoadFunc is such a callback. It's usually used to assign the Ribbon to a "global" RibbonUI object in your VBA module. Using that, you can at any time trigger the Invalidate or InvalidateControl methods.
At the same time RibbonLoadFunc is triggered when the Ribbon is loaded, the "get" attributes of other controls are triggered. These are used to dynamically populate things like labels and images. If you want to change these dynamic settings at some point, that's when Invalidate or InvalidateControl come into play - they force the "get" callbacks to run.
You can also use these "get" callbacks to populate additional global objects with information about the controls, so that you can use that information "outside" the Ribbon environment.
And that's basically the answer to your question: You can't use the RibbonLoadFunc to access and display information about other Ribbon controls. But the same "loading" that triggers RibbonLoadFunc can also provide information on any controls that have the corresponding "get" callbacks for what you want to "know".
For example, if you had the getLabel="SubInVBA" attribute in the XML for the button, that can dynamically assign the label to the button and at the same time store that information in a global variable and display it (any time you want, from the variable) in a MsgBox.
Related
everyone,
I am new to VBA and would like to know if it is possible to execute a menu button from a WordAddIn.
In the picture you can see which button I would like to execute using VBA.
Unfortunately, I can't record it via macro.
The Word object model allows executing built-in ribbon controls using the CommandBars.ExecuteMso method which executes the control identified by the idMso parameter. This method is useful in cases where there is no object model for a particular command. Works on controls that are built-in buttons, toggleButtons, and splitButtons.
But in your case the control comes from a third-party add-in which doesn't expose IDs and the CommandBars.ExecuteMso method can't find it and invoke the command programmatically.
To get the job done you may consider using the Microsoft Active Accessibility which is a Component Object Model (COM)-based technology that improves the way accessibility aids work with applications running on Microsoft Windows. It provides dynamic-link libraries that are incorporated into the operating system as well as a COM interface and API elements that provide reliable methods for exposing information about UI elements.
Also you may contact the add-in vendor for providing public methods that can be called from your solution. That's also a possible workaround instead of calling UI elements on the ribbon.
I designed the form below:
I would like the Subject to be automatically populated with the value of "[Machine] - [TAT]" as soon as those values are filled. I don't know how to access the values of these fields, the syntax for the value change listeners, nor where I should be putting this code.
When I click "Visual Basic", all I see is this:
It seems that this is only programmatic access to the Application, not the form.
How do I programmatically access the form that I designed?
Legacy form customizations require using VBScript for the "code behind", primarily for interactions with your custom UI. However, VBA macros are used independent of custom forms to work with Outlook items and data. If the business logic for your custom form requires working with the active MailItem, then VBScript is what you need to use.
For your scenario, you need to trap changes to the values of your custom controls. The best practice is to create custom fields in the Outlook item and map those fields to the controls. If you don't, you will only be able to write validation formulas in the designer for those controls, and you cannot trap value changes (odd, I know). Luckily custom fields fire the Item_CustomPropertyChange event, which is exactly what you need.
For more info, see:
Manipulating Controls Programmatically
MailItem.CustomPropertyChange Event
I am writing my first VBA Add-In under Microsoft Office Word 2007 with Windows 7 Pro/64. Part of this Add-In is a UserForm. Using the Visual Basic editor that runs from Word, I find there are two ways of viewing, and two ways of modifying a UserForm's properties:
View all properties from Object Browser (F2)
View some properties and edit them from Properties Window (F4)
Manually enter and edit any property from the Code window (F7)
Here is a screenshot of my Properties and Code windows:
A problem I find is that the Properties Window contains only a subset of the UserForm's properties (notice that CanPaste, CanRedo, and CanUndo don't appear in Properties), and changes made in the Properties Window are overridden by changes made in the Code window (e.g., at runtime, Me.Caption from the Code window above overrides the Caption field in Properties).
I suppose I should avoid using Properties at all then, and enter all settings via UserForm_Initialize as shown above. But (a) for some settings, Properties makes several settings at once. For example, selecting Verdana Bold from Properties equals Font = Verdana and Font.Bold = True in Code. And (b) it seems Properties sets the subset of properties it controls to defaults of its choosing, and if I change them I can't see what they started out as.
I therefore desire unified and comprehensive access to all my UserForm's properties at once, including the aforementioned default settings. Does anyone know how to reveal a UserForm's default settings as code, or to automatically open all its current settings in the Code window? Is there an umbrella mechanism I'm not aware of?
I'm not a veteran VBA programmer, but I can't believe my experience is unique. I've searched the 'net in vain for a solution. How do you with more experience manage this dilemma?
You use the Properties window to set appearance-related properties at design time. Those property values will then always apply unless you explicitly change them at run-time with VBA code.
Properties that don't relate to appearance, such as CanPaste and CanRedo relate to the state of the form at run-time, so it doesn't make sense to have them configurable at design-time.
You can change nearly all of the properties at run-time, whether it is in the Initialize event or elsewhere. You can even add controls at run-time, but your changes won't be persisted once the instance of the form terminates.
Here is my scenario:
I have an old excel project with macros that I've imported in a vsto project.
I have designed a custom ribbon (startFromScratch = true) to make it look like a dictator application.
I still want to use the existing macro code since it would take too much time to translate all the vba code in c# code
I have a class that is marked with the [ComVisible(true)] attribute so that I can call vsto methods from the vba code.
The problem is that I can't hide tabs, I can't get the ribbon to refresh. I can change the state of other controls (e.g. set checked state for CheckBox), but I can't hide or disable my custom tabs.
I have tried PerformLayout(), PerformDynamicLayout() on the ribbon, ribbon.RibbonUI.Invalidate(), but nothing works, the tab never changes state, although in code I set its visible property to false.
What do I need to do in order to refresh the ribbon at runtime?
Edit:
I just tried the same thing by exporting the ribbon to xml and the Invalidate() method works as expected. Is there any way to accomplish this for a ribbon designed with the visual editor?
I've replicated your problem when I set the StartFromScratch property of the ribbon to True, but it goes away when I set it to False. This is confirmed by MSDN.
You cannot change the visibility of custom tabs at run time if this property is set to true.
As a workaround, set StartFromScratch to False, add in a tab for each default tab, setting the ControlIdType of each to Office and the OfficeId of each to their default name (TabHome, TabFormulas, etc.), then set each of these built-in tab's visibility to False. (MSDN has made available a full list of control IDs for their Office apps for easy reference.)
Is there a way to read/get the Label attribute of an Office 2007/2010 ribbon control in VBA? The only exposed properties appear to be Tag, ID, and Context.
I'm trying to use the getLabel and getVisible callbacks together--read the label and determine whether or not to show a control. I tried setting the Tag property in the getLabel callback, but the code won't compile as that property is read-only by then.
Any other suggestions for how to skin this cat welcome. Note that I cannot use a dynamic menu; this is under a split button, and has to stay there. Thanks in advance.
I suspect that VBA doesn't have access to customize the Ribbon UI. I do know for a fact that this can be handled with VSTO.