RibbonXml togglebutton OnAction not finding callback function - vba

I have a peculiar problem happening, which I haven't been able to solve despite hours of googling & tinkering.
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="OnHomeRibbonLoad">
<ribbon startFromScratch="true">
<tabs>
<tab id="tab_Home" label ="Home" visible="true">
<group id="grp_Navigate" label="Navigate" visible="true">
<button id="btn_Tasks" label="Tasks" onAction="OnAction" visible="true" imageMso="ViewAllProposals" size="large" />
<toggleButton id="btn_Parties" label="Parties" onAction="OnAction" getPressed="GetPressed" visible="true" imageMso="ViewAllProposals" size="large" />
<button id="btn_Memos" label="Memos" onAction="OnAction" visible="true" imageMso="AccessTableIssues" size="large" />
</group>
</tab>
</tabs>
</ribbon>
<backstage onShow="OnBackstageShow">
<button id="btn_Login" label="Login" insertAfterMso="TabPrint" visible="true" getEnabled="GetEnabled" onAction="OnAction" isDefinitive="true"/>
<tab id="tab_Settings" label="Settings" insertAfterMso="TabPrint" visible="true" getEnabled="GetEnabled" ></tab>
<tab id="tab_Welcome" label="Welcome" insertAfterMso="TabPrint" visible="true" > </tab>
<tab idMso="TabPrint" visible="false"/>
<button idMso="ApplicationOptionsDialog" visible="false"/>
</backstage>
I have the above custom UI xml, and changed one of the buttons to be a togglebutton instead (id="btn_Parties"). All three buttons were working fine before, but after the togglebutton can't find its onAction callback function. The other two buttons trigger fine, but clicking the togglebutton results in an error saying... "Microsoft Access cannot run the macro or callback function 'OnAction'. Make sure the macro or function exists and takes the correct parameters".
Public Sub OnHomeRibbonLoad(ribbon As IRibbonUI)
Set HomeRibbon = ribbon
End Sub
Public Sub OnAction(control As IRibbonControl)
Select Case control.ID
Case "btn_Tasks"
MsgBox "Load TaskView"
Case "btn_Parties"
MsgBox "Load PartyView"
Case "btn_Memos"
MsgBox "Load MemoView"
Case Else
Debug.Print "Missing case in OnAction: " & control.ID
End Select
End Sub
Public Sub GetPressed(control As IRibbonControl, ByRef returnedVal)
Select Case control.ID
Case "tbtn_Parties"
returnedVal = IsPartiesLoaded
Case Else
returnedVal = True
Debug.Print "Missing case in GetEnabled: " & control.ID
End Select
End Sub
Is there something special about togglebutton that makes its OnAction event different to standard button?
If anyone can see where I'm going wrong, that would be much appreciated. Thanks.

The onAction callback for the toggleButton control should look like the following one:
C#: void OnAction(IRibbonControl control, bool pressed)
VBA / VB: Sub OnAction(control As IRibbonControl, pressed As Boolean)
C++: HRESULT OnAction([in] IRibbonControl *pControl, [in] VARIANT_BOOL *pvarfPressed)
Read more about the Fluent UI (aka Ribbon UI) in the following series of articles:
Customizing the 2007 Office Fluent Ribbon for Developers (Part 1 of 3)
Customizing the 2007 Office Fluent Ribbon for Developers (Part 2 of 3)
Customizing the 2007 Office Fluent Ribbon for Developers (Part 3 of 3)

Related

update ribbon label and image based on values in a table

I have a custom ribbon, I'd like to make one of the buttons dynamic based on values in a table
so, when the form is closed, I'd like for the ribbon button and label to change based on changes made in the form (if there were any)
Here's my VBA code just for that button.
And I created 2 separate buttons with different images and labels in the USysRibbonImages table. I have mine setup a tad different, that table also stores button names, macro names and labels, besides the images. I did it that way since each image record can only be tied to one button anyway, so, figured I might as well make my images into buttons in the same table. And this process is automated somewhat. I'm explaining in case someone wonders why the code is a little different from what you usually see for ribbons.
But it works fine for static ribbons, it's once I want to make them a little dynamic is where I have issues
Public Sub fnGetRibbonImages(control As IRibbonControl, ByRef image)
Dim attach As Attachment
DoCmd.OpenForm "fZRibbonImages", acNormal, , , , acHidden
If control.ID = "btnServicesShippingWeightBucketsCollections" Or control.ID = "btnServicesShippingWeightBucketsCollectionsRed" Then
'regular
If dCount("MissingServicesShippingWeightBucketsID", "MissingServicesShippingWeightBuckets") > 0 Then
Forms("fZRibbonImages").Filter = "([USysRibbonImages].[ButtonName]='btnServicesShippingWeightBucketsCollections')"
Else
'red
Forms("fZRibbonImages").Filter = "([USysRibbonImages].[ButtonName]='btnServicesShippingWeightBucketsCollectionsRed')"
End If
Forms("fZRibbonImages").FilterOn = True
Set attach = Forms("fZRibbonImages").Controls.Item("Images")
Set image = attach.PictureDisp()
End If
DoCmd.Close acForm, "fZRibbonImages", acSaveYes
End Sub
Public Sub GetRibbonLabel(ByVal control As Office.IRibbonControl, ByRef returnedVal)
If control.ID = "btnServicesShippingWeightBucketsCollections" Or control.ID = "btnServicesShippingWeightBucketsCollectionsRed" Then
If dCount("MissingServicesShippingWeightBucketsID", "MissingServicesShippingWeightBuckets") > 0 Then
returnedVal = "FIX!!!!!"
Else
returnedVal = "Buckets"
End If
End If
End Sub
And here's my ribbon xml (I removed a bunch of buttons, the code is the same for all)
<?xml version="1.0" encoding="utf-8"?>
<customUI
xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="OnLoadRibbon" loadImage="OnLoadImage">
<ribbon startFromScratch="true">
<tabs>
<tab id="tabDefault" label="App Options">
<group id="grpMappings" label="Mappings">
<button id="btnZoneXWalk" label="Zone Xwalk" onAction="mZoneXWalk" getImage="fnGetRibbonImages" size="large"/>
<button id="btnServicesShippingWeightBucketsCollections" label="Shipping Weight Buckets" onAction="mServicesShippingWeightBucketsCollections" getImage="fnGetRibbonImages" size="large"/>
</group>
</tab>
</tabs>
</ribbon>
</customUI>
I tried putting this with the CLOSE button for the form
sbRefreshRibbon
MyRibbon.Invalidate
And here's the code for the sbRefreshRibbon sub
Public Sub sbRefreshRibbon()
On Error GoTo RestartApp
MyRibbon.Invalidate
On Error GoTo 0
Exit Sub
RestartApp:
MsgBox "Please restart Application for Ribbon changes to take effect", _
vbCritical, "Ribbon Refresh Failed"
End Sub
No luck, except after a few changes (don't remember exactly what I did, I've been at this for a while) I got an error that said to restart to reload the ribbon
Instead of the label attribute for the ribbon controls you need to use the getLabel one with a callback which should have the following signature:
C#: string GetLabel(IRibbonControl control)
VBA: Sub GetLabel(control As IRibbonControl, ByRef label)
C++: HRESULT GetLabel([in] IRibbonControl *pControl, [out, retval] BSTR *pbstrLabel)
Visual Basic: Function GetLabel(control As IRibbonControl) As String
So, in your ribbon XML file you need to replace the label attribute:
<group id="grpMappings" label="Mappings">
<button id="btnZoneXWalk" label="Zone Xwalk" onAction="mZoneXWalk" getImage="fnGetRibbonImages" size="large"/>
<button id="btnServicesShippingWeightBucketsCollections" getLabel="GetRibbonLabel" onAction="mServicesShippingWeightBucketsCollections" getImage="fnGetRibbonImages" size="large"/>
</group>
Read more about the Fluent UI (aka Ribbon UI) in the following articles:
Customizing the 2007 Office Fluent Ribbon for Developers (Part 1 of 3)
Customizing the 2007 Office Fluent Ribbon for Developers (Part 2 of 3)
Customizing the 2007 Office Fluent Ribbon for Developers (Part 3 of 3)

How to enable/disable buttons on the Excel ribbon via VBA

Within an Excel add-in I'm developing, I make a call to an API and send over the users activation key. If the API recognises the key then it returns a token which means the user is authenticated. Once authenticated, I want to enable the buttons on my add-in's ribbon. So unless they're authorised, they don't get to use it.
My ribbon xml file looks like:
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="OnRibbonLoad">
<ribbon>
<tabs>
<tab id="CustomTab" getLabel="GetLabel" insertBeforeMso= "TabDeveloper">
<group id="GroupA" getVisible = "GetVisible" getLabel="GetLabel">
<button id="aButton01" getLabel="GetLabel" onAction="RunMacro" getImage="GetImage" getSize="GetSize" getScreentip = "GetScreentip" getVisible = "GetVisible" getEnabled="GetEnabled" />
</group>
<group id="GroupB" getVisible = "GetVisible" getLabel="GetLabel">
<button id="bButton01" getLabel="GetLabel" onAction="RunMacro" getImage="GetImage" getSize="GetSize" getScreentip = "GetScreentip" getVisible = "GetVisible" getEnabled="GetEnabled" />
<button id="bButton02" getLabel="GetLabel" onAction="RunMacro" getImage="GetImage" getSize="GetSize" getScreentip = "GetScreentip" getVisible = "GetVisible" getEnabled="GetEnabled" />
<button id="bButton03" getLabel="GetLabel" onAction="RunMacro" getImage="GetImage" getSize="GetSize" getScreentip = "GetScreentip" getVisible = "GetVisible" getEnabled="GetEnabled" />
</group>
</tab>
</tabs>
</ribbon>
</customUI>
I assign various properties to the buttons via helper methods. An example of the GetVisible one:
Sub GetVisible(control As IRibbonControl, ByRef MakeVisible)
'PURPOSE: Show/Hide buttons based on how many you need (False = Hide/True = Show)
Select Case control.ID
Case "GroupA": MakeVisible = True
Case "aButton01": MakeVisible = True
Case "GroupB": MakeVisible = True
Case "bButton01": MakeVisible = True
Case "bButton02": MakeVisible = True
Case "bButton03": MakeVisible = True
End Select
End Sub
My OnRibbonLoad method is:
Dim MyRibbonUI As IRibbonUI
Private Sub OnRibbonLoad(ribbonUI As IRibbonUI)
Dim Authenticate As New AuthenticationClass
Set MyRibbonUI = ribbonUI
' Enable/Disable buttons based on authentication status
If Authenticate.Authentify = False Then
' Lock the Ribbon
Debug.Print ("Unauthorized!")
Else
' Unlock the Ribbon
Debug.Print ("Authorized!")
End If
End Sub
I have tried creating a GetEnabled method which I could call OnRibbonLoad which would toggle the availability of the buttons but I cannot figure out how I would go about calling it:
Sub GetEnabled(control As IRibbonControl, ByRef MakeEnabled)
Select Case control.ID
Case "GroupA": MakeEnabled = Enabled
Case "aButton01": MakeEnabled = Enabled
Case "GroupB": MakeEnabled = Enabled
Case "bButton01": MakeEnabled = Enabled
Case "bButton02": MakeEnabled = Enabled
Case "bButton03": MakeEnabled = Enabled
End Select
End Sub

Activate Format Painter with the equivalent effect to double clicking

I know that ALT+H,F,P activates Format Painter, but this only activates it for your next selection, whereas a double click on Format Painter activates the tool until the user hits ESC key.
I would like Excel 2010 VBA code that activates Format Painter for more than one selection, until I hit ESC. Basically, I am requesting VBA code that activates the double click setting of Format Painter.
I remembered having it in my Code-library. I am also uploading Sample macro file which has 3 Buttons Toggle Copy, Toggle Cut and Toggle Paste. When you press say Toggle Copy Button you will see on ribbon this feature getting enabled or disabled. HTH
Ribbon_xml_macro.xlsm https://www.dropbox.com/s/rrg292652ug137g/Ribbon_xml_macro.xlsm?dl=0
Use this ribbon xml which contains disable commands.
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
<commands>
<!-- Disablae right click menu -->
<command idMso="Cut" enabled="false"/>
<command idMso="Copy" enabled="false"/>
<command idMso="Paste" enabled="false"/>
<command idMso="PasteMenu" enabled="false"/>
<command idMso="PasteAsPictureMenu" enabled="false"/>
</commands>
</customUI>
Use this ribbon xml which contains enable commands.
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="rxIRibbonUI_onLoad">
<commands>
<!-- Disablae right click menu -->
<command idMso="Cut" getEnabled="rxshared_getEnabled"/>
<command idMso="Copy" getEnabled="rxshared_getEnabled"/>
<command idMso="Paste" getEnabled="rxshared_getEnabled"/>
<command idMso="PasteMenu" getEnabled="rxshared_getEnabled"/>
<command idMso="PasteAsPictureMenu" getEnabled="rxshared_getEnabled"/>
</commands>
</customUI>
Code in xlsm standard code module
Private m_blnCutEnabled As Boolean
Private m_blnCopyEnabled As Boolean
Private m_blnPasteEnabled As Boolean
Private m_rbxRibbon As IRibbonUI
Sub ToogleCut()
m_blnCutEnabled = Not m_blnCutEnabled
m_rbxRibbon.Invalidate
End Sub
Sub ToogleCopy()
m_blnCopyEnabled = Not m_blnCopyEnabled
m_rbxRibbon.Invalidate
End Sub
Sub TooglePaste()
m_blnPasteEnabled = Not m_blnPasteEnabled
m_rbxRibbon.Invalidate
End Sub
Sub rxIRibbonUI_onLoad(ribbon As IRibbonUI)
Set m_rbxRibbon = ribbon
End Sub
Sub rxshared_getEnabled(Control As IRibbonControl, ByRef returnedVal)
Select Case Control.ID
Case "Cut"
returnedVal = m_blnCutEnabled
Case "Copy"
returnedVal = m_blnCopyEnabled
Case "PasteMenu", "Paste", "PasteAsPicture"
returnedVal = m_blnPasteEnabled
End Select
End Sub

Create gallery with images in Excel

I am trying to make smth like this:
For now I use the imageMso attribute just for testing purposes. Even though, nothing really happens.
That's the XML for the gallery:
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="Ribbon_Load">
<ribbon>
<tabs>
<tab idMso="TabAddIns" label="Gallery">
<group id="grpGallery" label="Example Gallery">
<gallery id="galleryID" label="My Gallery" columns="3" rows="2" size="large"
itemHeight="100" itemWidth="100"
getItemID="CallbackGetItemID"
getItemCount="CallbackGetItemsCount"
getItemImage="CallbackGetItemImage"
getItemScreentip="CallbackGetItemScreentip"
getItemSupertip="CallbackGetItemSupertip">
<item id="galImg1" imageMso="PictureBrightnessGallery"/>
<item id="galImg2" imageMso="ZoomPrintPreviewExcel"/>
</gallery>
....
And the VB code to it:
Public idCounter As Integer
Public Sub New()
idCounter = 0
End Sub
Public Function GetCustomUI(ByVal ribbonID As String) As String Implements Office.IRibbonExtensibility.GetCustomUI
Return GetResourceText("GalleryTest.Gallery.xml")
End Function
#Region "Ribbon Callbacks"
Public Sub Ribbon_Load(ByVal ribbonUI As Office.IRibbonUI)
Me.galleryRibbon = ribbonUI
End Sub
Public Sub CallbackGetItemID(control As Microsoft.Office.Core.IRibbonControl, _
index As Integer, ByRef itemID As Integer)
itemID = idCounter
idCounter += 1
End Sub
Public Sub CallbackGetItemsCount(control As Microsoft.Office.Core.IRibbonControl, _
ByRef count As Integer)
count = 6
End Sub
Public Sub CallbackGetItemScreentip(control As Microsoft.Office.Core.IRibbonControl, _
Index As Integer, ByRef screentip As String)
screentip = "Screentip"
End Sub
Public Sub CallbackGetItemSupertip(control As Microsoft.Office.Core.IRibbonControl, _
Index As Integer, ByRef supertip As String)
'TO DO'
End Sub
As you see, it's nothing fancy. I am just getting into the vb.net + excel world. What happens is that I get the "My Gallery" button for the dropdown, in the excel tab, but it is empty. No elements. Not even the dummy items.
Any suggestions?
P.S. I followed this documentation
Try to return actual values in the callbacks. For example, I see non-existing IDs in the callback.
There is no need to add the CallbackGetItemsCount callback for the gallery control if you specified items explicitly.
You can read more about the Ribbon UI in the following series of articles in MSDN:
Customizing the 2007 Office Fluent Ribbon for Developers (Part 1 of 3)
Customizing the 2007 Office Fluent Ribbon for Developers (Part 2 of 3)
Customizing the 2007 Office Fluent Ribbon for Developers (Part 3 of 3)

access 2010 custom ribbon

I have a custom ribbon that calls vba commands. When it does, I get the error message
Microsoft Access cannot run the macro or callback function [FUNCTION OR SUB]
where [FUNCTION OR SUB] is the Function or Sub name I am calling.
An example of the code that generates the above message is:
Public Function OnButtonPress2(ctl As IRibbonControl)
MsgBox "OnButtonPress2"
End Function
Where OnButtonPress2 is called in the ribbon's XML file for a button as
onAction="OnButtonPress2
The above works for a macro, so it's likely not to be the ribbon's xml
======== VERSION 2
I've created a new simple test db with the XML and module shown below:
The results of each are:
Macro1 - works fine (it has a popup message)
CommandOnAction2 - msgbox "There was an error compiling this function"
OnButtonPress2 - msgbox "Microsoft Access cannot run the macro or callback function 'OnButtonPress2 '
on the line "Public gobjRibn As IRibbonUI", IRibbonUI does not autocomplete leading me to believe there is a reference that needs to be added
XML (Ribbon name is NewRibbon and is set to open on startup)
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
<ribbon startFromScratch="false">
<tabs>
<tab id="tab1" label="Your Custom Tab">
<group id="group1" label="Your Custom Group">
<button id="SampleButton" label="Macro1" onAction="Macro1" />
<button id="SampleButton2" label="CommandOnAction2" onAction="=CommandOnAction2()" />
<button id="SampleButton3" label="OnButtonPress2" onAction="OnButtonPress2" />
</group>
</tab>
</tabs>
</ribbon>
</customUI>
module (name is modRibbon)
Option Compare Database
Public gobjRibn As IRibbonUI
Public Function CommandOnAction2(ByVal ctl As IRibbonControl)
MsgBox "Function CommandOnAction2"
End Function
Public Sub OnButtonPress2(ByVal ctl As IRibbonControl)
MsgBox " Sub OnButtonPress2"
End Sub
I was able to recreate your issue in Access 2010 and I got your example to work by changing the Function to a Sub that looks like this:
Public Sub OnButtonPress2(ByVal control_ As IRibbonControl)
MsgBox "OnButtonPress2"
End Sub
BTW, while searching for information on this issue I stumbled upon a posting in another forum here. In it, Albert D. Kallal discusses using onAction="=MyPublicFunctionName()" as an alternative to callbacks; perhaps you may find that useful in some cases.