Dynamically changes ribbon's button label Excel - excel

I am using the following piece of XML code to create a custom Ribbon for an Excel add-in.
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
<ribbon startFromScratch="false">
<tabs>
<tab id="ComdinheiroTab" label="COMDINHEIRO">
<group id="ComdinheiroButtons" label="Comdinheiro">
<button id="Login" getLabel="getLabelLogin" image="Login" size="large" onAction="OnActionLogin"/>
</group>
</tab>
</tabs>
</ribbon>
</customUI>
I am using the following VBA code to set a label for the button login:
Sub getLabelLogin(control As IRibbonControl, ByRef returnedVal)
if loggedIn = true then
returnedVal = "Logged"
else
returnedVal = "Disconected"
end if
End Sub
The label's name changes successfully according to the variable loggedIn's value when the ribbon is loaded. However I wish I could change the label's values during the execution of my program. Is it possible to call getLabel event using a VB code? Is there anyway to refresh my ribbon so this event would be called again?

Yes, it's possible to run "get" callbacks later on. In order to do so, you need to create a module- or global-level variable to hold the "ribbon UI" object. That object has two useful methods: Invalidate and InvalidateControl. The first triggers all the "get" callbacks in the Ribbon XML. The second triggers the callbacks only for the specified control.
Your ribbon ui must be assigned to this object when the Ribbon loads. In order for this to happen, you need the attribute onLoadin the customUI tag of your Ribbon XML and its callback in your VBA.
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="ribbonLoaded">
<ribbon startFromScratch="false">
<tabs>
<tab id="ComdinheiroTab" label="COMDINHEIRO">
<group id="ComdinheiroButtons" label="Comdinheiro">
<button id="Login" getLabel="getLabelLogin" image="Login" size="large" onAction="OnActionLogin"/>
</group>
</tab>
</tabs>
</ribbon>
</customUI>
In the VBA sample code, below, UpdateTheLabel is called from "the execution of my program" mentioned in the question. This procedure need not be connected to the RibbonXML in any way.
UpdateTheLabels action, however, is connected to the Ribbon: by calling InvalidateControl it causes a Ribbon control ("Login", in this case) to re-evaluate all its dynamic ("get") call-backs, such as getLabelLogin (which is in the Ribbon XML).
Dim ribbonUI as IRibbonUI
Sub ribbonLoaded(ribbon as IRibbonUI)
Set ribbonUI = ribbon
End Sub
Sub UpdateTheLabel
ribbonUI.InvalidateControl("Login")
End Sub
Sub getLabelLogin(control As IRibbonControl, ByRef returnedVal)
if loggedIn = true then
returnedVal = "Logged"
else
returnedVal = "Disconected"
end if
End Sub
It doesn't matter what procedure calls InvalidateControl as long as the procedure has access to the ribbonUI object.
More on this can be found in the MSDN article https://msdn.microsoft.com/en-us/library/aa338202(v=office.12)#OfficeCustomizingRibbonUIforDevelopers_Dynamically

Related

Getting a Dropdown to Work in a Customised Excel Ribbon

So I'm creating a custom Ribbon using the Office RibbonX Editor and Excel. I want to display a simple dropdown that allows the user to switch between three worksheets.
I'm not sure why it's going wrong, but I keep running into three errors that correspond to the onAction attribute for each item:
Ln 8, Col 51: The 'onAction' attribute is not declared.
Ln 9, Col 51: The 'onAction' attribute is not declared.
Ln 10, Col 51: The 'onAction' attribute is not declared.
Here is my code:
XML (customUI14.xml file):
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
<ribbon>
<tabs>
<tab id="customTab" label="DropDown" insertAfterMso="TabHome">
<group id="customGroup" label="Custom Group">
<dropDown id="dropDown1" label="Dropdown Box">
<item id="dd01" label="Sheet1" imageMso = "_1" onAction="DDOnAction" />
<item id="dd02" label="Sheet2" imageMso = "_2" onAction="DDOnAction" />
<item id="dd03" label="Sheet3" imageMso = "_3" onAction="DDOnAction" />
</dropDown>
</group>
</tab>
</tabs>
</ribbon>
</customUI>
VBA:
Sub DDOnAction(control As IRibbonControl, id As String, index As Integer)
Select Case control.id
Case "dd01"
ActiveWorkbook.Sheets("Sheet1").Activate
Case "dd02"
ActiveWorkbook.Sheets("Sheet2").Activate
Case "dd03"
ActiveWorkbook.Sheets("Sheet3").Activate
End Select
End Sub
Hi the onAction attribute should placed in the dropdown and not in the item,
So the XML is :
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
<ribbon>
<tabs>
<tab id="customTab" label="DropDown" insertAfterMso="TabHome">
<group id="customGroup" label="Custom Group">
<dropDown id="dropDown1" label="Dropdown Box" onAction="DDOnAction" >
<item id="dd01" label="Sheet1" imageMso = "_1" />
<item id="dd02" label="Sheet2" imageMso = "_2" />
<item id="dd03" label="Sheet3" imageMso = "_3" />
</dropDown>
</group>
</tab>
</tabs>
</ribbon>
</customUI>
and the code is like this
Sub DDOnAction(control As IRibbonControl, id As String, Index As Integer)
Select Case Index
Case 0
ActiveWorkbook.Sheets("Sheet1").Activate
Case 1
ActiveWorkbook.Sheets("Sheet2").Activate
Case 2
ActiveWorkbook.Sheets("Sheet3").Activate
End Select
End Sub

Ribbon XML: Custom Excel Tab Disappears with Addition of Menu

Heylo, I am having a rather frustrating issue with my custom Excel Tab. I currently have about 20 buttons that all do a variety of different things, and I would like to implement some menu's to declutter the tab a bit. I have an add-in with a bunch of macros and an embedded customUI.xml file to organize all of the buttons.
The problem is, whenever I try to add what I see as perfectly fine menu xml code to the customUI.xml file, and re-embed it in the add-in, the tab ceases to show up when I reload Excel. Before I put the menu in, the tab is there and everything is fine, but when I add the menu code, it just doesn't want to show up anymore. Below is an example of what I'm trying to do.
<customUI xmlns = "http://schemas.microsoft.com/office/2006/01/customui">
<ribbon>
<tabs>
<tab id = "MyTab" label = "My Tab">
<group id = "About" label = "About">
<button id = "Button1"
label = "About My Tab"
size = "large"
onAction = "AboutMyTab"
imageMso = "Help"
screentip = "About My Tab"
supertip = "Shows a dialog box that displays information about My Tab."
/>
</group>
<group id = "TestMenus" label = "My Test Menu">
<menu id = "MyMenu" label = "The Menu">
<button id = "ButtonX" label = "X" size = "large" imageMso = "FileSave" />
<button id = "ButtonY" label = "Y" size = "large" imageMso = "Bold" />
<button id = "ButtonZ" label = "Z" size = "large" imageMso = "Undo" />
</menu>
</group>
</tab>
</tabs>
</ribbon>
</customUI>
Whether I embed the menu in a group or not, it still causes the tab to not show up at all. Is it the schema I am using? I am confused on what I am doing wrong. Also, I am using Excel 2016 if that helps in any way.
Thank you for any help in advance.
You need to remove Size property from buttons in menu and add it to menu itself:
<menu id = "MyMenu" label = "The Menu" itemSize = "large">
<button id = "ButtonX" label = "X" imageMso = "FileSave" />
<button id = "ButtonY" label = "Y" imageMso = "Bold" />
<button id = "ButtonZ" label = "Z" imageMso = "Undo" />
</menu>

How to click Save button on a web form using VBA

I am working on automating a task. I want to click a Save button on a web form using VBA, but it's not working:
<input name="save" title="Save" class="btn" type="submit" value=" Save ">
<input name="save" tabindex="79" title="Save" class="btn" type="submit" value=" Save ">
I've tried ie.Document.all("save").Click, but it doesn't seem to work. What method do I need to click the button?
You can try going through all your "btn" class collection, and click the one with your save value:
Dim btnClassColl As Object, btn As Object
Set btnClassColl = ie.document.getElementsByClassName("btn")
For Each btn In btnClassColl
If btn.Value Like "*save*" Then
btn.Click
Exit For
End If
Next
Also: make sure that your web page has FULLY loaded before trying to automate anything.
Edit
In response to the comment:
This code is neither giving error nor its clicking on btn. Can this be because there are two buttons on web page with same name and function?
An alternative solution would be that if you know the index number of the collection item, you can simply use that index number and not loop at all. In this case, your index # is 1 (remember: Base 0).
Try this alternative:
Dim btn As Object
ie.document.getElementsByName("save")(1) '1 actually means #2 in index

How to re-trigger GetCustomUI() from ExcelDNA

I have, in ExcelDNA, created a custom ribbon (extending ExcelRibbon) and overridden the GetCustomUI() method to create a menu control from a list of strings. Basically:
public override string GetCustomUI(string RibbonID)
{
string customUIXml =
#"<customUI xmlns='http://schemas.microsoft.com/office/2006/01/customui' loadImage='LoadImage' onLoad='OnRibbonLoaded' >
<ribbon>
<tabs>
<tab id='CustomTab' label='My Dynamic Tab'>
<group id='SampleGroup' label='My Sample Group'>
<menu description='description' enabled='true' id='menuItem' visible='true' size='normal' >";
foreach (string itemName in _ItemNameList)
customUIXml += $"<button id='btn_tool_{itemName}' label='{itemName}' onAction='MyMethod' />";
customUIXml +=
#"</menu>
</group >
</tab>
</tabs>
</ribbon>
</customUI>";
return customUIXml;
}
Because _ItemNameList is retrieved from a different file/system, I can't place this customUI tag directly into the .dna file (as far as I know) and hence I build it on load via the GetCustomUI().
As a proof of concept, the onAction method will add a new item to _ItemNameList when the user clicks on a menu item.
But how do I get Excel to call GetCustomUI again in order to have the XML rebuilt?
I have tried invalidating the ribbon object itself, but this does not trigger Excel to call GetCustomUI again.
The next best thing I can think of (although I'm still to test this) is to create a menu with a whole load of invisible 'placeholder' buttons (by specifying the getVisible callbacks) and when the user clicks on a button, just invalidate the button that needs to now become visible, showing the new item added to _ItemNameList. I still need to think through how to get the correct button reference though... This also feels a little dirty.
Any ideas how to have Excel rebuild the ribbon?
Also open to other ideas to allow me to add items to a menu in an ExcelRibbon.
I think you are looking for the dynamicMenu control, which will trigger an event to let you dynamically set the contents of the menu, every time you click on it.
Something like this:
<?xml version="1.0" encoding="utf-8" ?>
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="OnLoad">
<ribbon>
<tabs>
<tab id="MyAwesomeRibbon" label="My Awesome Ribbon">
<group id="MyDynamicGroup" label="Hello Dynamic!">
<dynamicMenu id="MyDynamicMenu"
label="Click for Awesome"
getContent="OnGetContent"
invalidateContentOnDrop="true"
size="large"
imageMso="HappyFace" />
</group>
</tab>
</tabs>
</ribbon>
</customUI>
Your OnGetContent method will get fired every time the user clicks on the ribbon button, so you can dynamically assemble the items.
e.g.
public string OnGetContent(IRibbonControl control)
{
var menuXml = #"
<menu xmlns='http://schemas.microsoft.com/office/2006/01/customui' itemSize='large'>
<button id='SaveButton'
label='Save'
onAction='OnSave'
imageMso='FileSave' />
<button id='AboutButton'
label='About...'
onAction='OnAbout'
imageMso='FileDocumentInspect' />
</menu>";
return menuXml;
}
Of course, you'd have to build this string dynamically from your list, etc.

How to define size of a button in Excel 2013 using customUI editor

I am trying to create a new ribbon with 2 buttons in Excel 2013. I was able to create it using Custom UI editor thanks to
Excel CustomUI ribbon layout and How to add a custom Ribbon tab using VBA?
When I input the code as
<button id="aa" label="CORE" onAction = "HMA_CORE"/>
it works but once I try this code
<button id="aa" label="CORE" size = "large" onAction = "HMA_CORE"/>
and then click validate in the customUI it says that "size attribute is not declared". I am not sure what to add. I saw http://www.rondebruin.nl/win/s2/win009.htm as well, but the code looks the same.
Any help will be appreciated.
Thanks
The code for the buttons looks like this
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
<ribbon>
<tabs>
<tab id="toolRibbon" label="HMA-FUNCTIONS">
<group id="groupDocument" label="HMA-xml outputs">
<buttonGroup id="a">
<button id="aa" label="CORE" onAction = "HMA_CORE"/>
<button id="ab" label="PLANT" onAction = "HMA_PLANT"/>
</buttonGroup>
</group>
</tab>
</tabs>
</ribbon>
</customUI>
Give this a try using built in icons from Office (get rid of buttonGroup)
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
<ribbon>
<tabs>
<tab id="toolRibbon" label="HMA-FUNCTIONS" insertBeforeMso="TabHome">
<group id="groupDocument" label="HMA-xml outputs">
<button id="aa" label="CORE" imageMso="MacroArguments" onAction = "HMA_CORE" size="large" />
<button id="ab" label="PLANT" imageMso="PictureBrightnessGallery" onAction = "HMA_PLANT" size="large" />
</group>
</tab>
</tabs>
</ribbon>
</customUI>
Reference: Office 2007 Icons Gallery
the problem was the space between the "size" and the "larger" statement! put it all together
error >> size = "larger"
correct >> size="larger"

Resources