Intro:
I have written some short excel macros (tested, they work fine) and want to link them to a button in the Ribbon (Excel 2010). I had already done it successfully in Excel 2007.
I am using Custom UI Editor to build a new ribbon, which also works fine. Everything is packaged in a .xlam add-in and added to Excel. The ribbon shows up nicely, all other buttons works, but ...
Problem:
when I hit the button that is linked to the macro I get the error: "wrong number of parameters or property assignment not valid" (message translated from Italian, might not be exactly the same in English)
Troubleshooting info:
The macros do not have parameters. The same macros can be successfully called and executed manually. I am even able to add the same macros to the Quick Access Toolbar.
Here is the specific portion of the ribbon script:
<group id="DupNumber" label="Number" insertBeforeMso="GroupNumber" >
<comboBox idMso="NumberFormatGallery"/>
<box id="HN1" boxStyle="horizontal">
<buttonGroup id="HNButtonGroup1">
<button id="Euro" onAction="Roberto.xlam!EURZ" imageMso="F" supertip="text ..."/>
<button id="EuroNZ" onAction="Roberto.xlam!EURNZ" imageMso="E" supertip="text ..."/>
<button idMso="PercentStyle"/>
<button id="Comma" onAction="Roberto.xlam!NewCommaFormat" imageMso="C" supertip="test ..."/>
<button idMso="PercentStyle"/>
</buttonGroup>
</box>
and here are the macros:
Sub EURZ()
Application.ActiveCell.NumberFormat = "€ #,##0.00"
End Sub
Sub EURNZ()
Application.ActiveCell.NumberFormat = "€ #,##0"
End Sub
Sub NewCommaFormat()
Application.ActiveCell.NumberFormat = "#,##0"
End Sub
Can you help me?
Thanks
Roberto
I believe you need to add this param to your macro: control As IRibbonControl
So it should look like this:
Sub EURZ(control As IRibbonControl)
Application.ActiveCell.NumberFormat = "€ #,##0.00"
End Sub
Related
Description: This is Excel 2013 VBA case. I created AddIn which should be able to install and uninstall another AddIns from AddIn list stored in global variable "listOfAddIns" which is Array of Arrays of Variant Type called "valueArray". There are "group control" buttons (for purpose of install or uninstall all available addins) and "individual control" toogle buttons (for install or uninstall specific AddIn). I use a lot of callback functions for purpose of full customization of all elements from VBA.
Problem: Everything works perfectly for installing/uninstalling AddIns without their own Ribbon Tabs. Once installed AddIn has its own Ribbon Tab, I am no longer able to use ribbon object .Invalidate method and call callbacks. I get this poorly descriped Error Message:
Run-Time error'-2147467259(80004005)': Method 'Invalidate' of object 'IRibbonUI' failed
My Idea: Due to described symptomns, I suspect, that there are some duplicity problems of IRibbonControl from different AddIns. Despite a lot of efforts, I cannot figure it out.
Relevant part of CustomUI XML:
<customUI onLoad="OnLoad" xmlns="http://schemas.microsoft.com/office/2006/01/customui">
<ribbon startFromScratch="false">
<tabs>
<tab id = "INST1ID" label="Installer">
<group id="GroupControls" label="Group controls">
<button id="B1ID" label="Install All" size="large" onAction="InstallAll" imageMso="AcceptInvitation" />
<button id="B2ID" label="Uninstall ALL" size="large" onAction="UninstallAll" imageMso="MasterViewClose" />
</group>
<group id="IndividualControls" label="Individual controls">
<toggleButton id="TB1ID" imageMso="HappyFace" label="AddIn1" onAction="TBsControl" size="large" tag="1" getEnabled="TBsGetEnabled" getPressed="TBsGetPressed" getVisible="TBsGetVisible" />
<toggleButton id="TB2ID" imageMso="HappyFace" label="AddIn2" onAction="TBsControl" size="large" tag="2" getEnabled="TBsGetEnabled" getPressed="TBsGetPressed" getVisible="TBsGetVisible" />
<toggleButton id="TB3ID" imageMso="HappyFace" label="AddIn3" onAction="TBsControl" size="large" tag="3" getEnabled="TBsGetEnabled" getPressed="TBsGetPressed" getVisible="TBsGetVisible" />
</group>
</tab>
</tabs>
</ribbon>
</customUI>
OnLoad Sub:
Public Sub OnLoad(ribbon As IRibbonUI)
Set ribbonObject = ribbon
End Sub
Main procedure for "Group control" example:
Public Sub InstallAll(control As IRibbonControl)
Call ResetSomePublicVariables
Call CreateEntryValuesAndFillToListOfAddIns
Call CheckAvailabilityAndInstallationOfAddInsAndFillToListOfAddIns
Call UpdateListOfAddInsToInstallAllAvailableAddIns
Call InstallOrUninstallAddInsDueToListOfAddIns
ribbonObject.Invalidate
End Sub
Main procedure for "Individual control" and expanded 4th Sub:
Public Sub TBsControl(control As IRibbonControl, pressed As Boolean)
Call ResetSomePublicVariables
Call CreateEntryValuesAndFillToListOfAddIns
Call CheckAvailabilityAndInstallationOfAddInsAndFillToListOfAddIns
Call UpdateListOfAddInsDueToToogleButtonRequest(control.tag, pressed)
Call InstallOrUninstallAddInsDueToListOfAddIns
ribbonObject.Invalidate
End Sub
Public Sub UpdateListOfAddInsDueToToogleButtonRequest(tag As Long, pressed As Boolean)
Dim valueArray() As Variant
valueArray = listOfAddIns(tag)
If pressed = True Then
valueArray(VAColumnIndex_Installed) = 1
Else
valueArray(VAColumnIndex_Installed) = 0
End If
listOfAddIns(tag) = valueArray
End Sub
Callback example:
Public Sub TBsGetVisible(control As IRibbonControl, ByRef returnedVal)
For Each Item In listOfAddIns
If control.tag = Item(VAColumnIndex_Number) Then
returnedVal = True
Exit For
Else
returnedVal = False
End If
Next Item
End Sub
I didnt used Custom UI Editor or similar software and I guess that it will not be helpful in this phase
I tried to move onLoad sub to ThisWorkbook module. I understand, that moving callbacks to ThisWorkbook is wrong way. I also tried ThisWorkbook and ThisAddin prefixes to IRibbonControl argument, but thats also wrong way. So far with my tries to somehow differentiate eventual IRibbonControl duplicities (my idea only).
I tried to rename IRibbonUI objects in other AddIns without any progress.
I read a lot of sources and saw a lot of examples and different approaches on Microsoft, StackOverFlow on link below but it didnt helped me with this.
https://excelguru.ca/?s=ribbon+part
Any ideas and especially simple solutions of this problem are very welcomed, thank you very much
Solved.
First line of XML file of all my AddIns looked like this and that was a source of all problems described before.
<customUI onLoad="OnLoad" xmlns="http://schemas.microsoft.com/office/2006/01/customui">
Same name for onLoad procedure in different AddIns resulted in described behaviour including earlier mentioned error when 2 or more AddIns with this same name was installed. Renaming onLoad procedures to different names solved everything instantly.
Source which helped me: https://excelguru.ca/debugging-ribbonx-invalidateinvalidatecontrol-failures%E2%80%A6/
I'm trying to find a ButtonBar solution to add to a sheet in excel (so not in forms, directly on the sheet)
While looking I ran into the ActivX controll: ButtonBar Class, that gets added like the code below.
Can anyone tell me how I can add buttons to this control?
Or do you know of any other buttonbar bype controls I could use on an Exel sheet?
ActiveSheet.OLEObjects.Add(ClassType:="UmOutlookAddin.ButtonBar.1", Link:= _
False, DisplayAsIcon:=False, Left:=96.75, Top:=15, Width:=214.5, _
Height:=17.25).Select
You can control the click unsing the code below, but I have not found a way to add new buttons:
Private Sub ButtonBar1_OnClick(ByVal ButtonId As Long)
I don't think you can add buttons. I tried changing the label and that crashed Excel:
Sub Test()
Dim bb As ButtonBar
Set bb = ActiveSheet.OLEObjects(1).Object
bb.SetButtonLabel PlayButtonId, "Test" 'Boom
End Sub
The ButtonBar seems too unstable and I would not recommend using it.
However, you have other options. For example, on the Developer tab you have the simple Button control:
You can add multiple buttons and then group them:
You could obviously make them adjacent to mimic a bar:
As you can see, they even have a 'pressed' animation when you click them (mid button).
If you don't need the animation then you can just add any shape to work as a button. You would add one shape and format it and then make copies and assign a different macro for each (with right click and Assign Macro...). You would then group them when done. For example:
Or, you could just use a custom ribbon tab if you don't necessarily need the buttons in the sheet itself. Here is an example where I showed step by step how to add a custom ribbon but there are many ways of doing it if you search the web. In that example the custom ribbon is not used to display anything but rather is used for it's Init event. But it's easy to replace the xml at step 2f with something like this:
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="InitRibbon">
<ribbon>
<tabs>
<tab id ="TestTabID" Label="Test">
<group id="FirstGroupID" Label="First Group">
<button id="RefreshData" label="Refresh Data" size="large" imageMso="Refresh" onAction="RibbonCallTool" />
<button id="UnloadData" label="Unload Data" size="large" imageMso="RecordsDeleteRecord" onAction="RibbonCallTool" />
</group>
</tab>
</tabs>
</ribbon>
</customUI>
in which case you would also have this method in a standard VBA module:
'*******************************************************************************
'Callback ("onAction"). Runs when a control is clicked in the Custom Ribbon tab
'*******************************************************************************
Public Sub RibbonCallTool(ByVal ctrl As IRibbonControl)
Select Case ctrl.ID
Case "RefreshData"
MsgBox "Refresh"
Case "UnloadData"
MsgBox "Unload"
Case Else
Debug.Print "Control <" & ctrl.ID & "> does not have an associated action attached!"
End Select
End Sub
Finally, you could always have a single button that opens a modeless form with all the menus you need.
I am trying to figure out how I can enable a ribbon button based on Selection, I know I need to use Worksheet_SelectionChange Event however I not sure how to proceed. I have exhausted all options looking on how to do it, can someone help with this please, I have asked on Mr Excel but no answers to what I need.
Example of what I am looking for is:
If a column is selected then enable ribbon button a or If a Row is selected then Enable ribbon button b
Use ribbon callbacks and call IRibbonUI.Invalidate or IRibbonUI.InvalidateControl where appropriate. See How to get the reference to the IRibbonUI in VBA? for more information.
You can customize the Ribbon UI by using callback procedures in VBA macros or COM add-ins. For each of the callbacks the add-in implements, the responses are cached. For example, if an add-in writer implements the getImage callback procedure for a button, the function is called once, the image loads, and then if the image needs to be updated, the cached image is used instead of recalling the procedure. This process remains in-place until the code signals that the cached values are invalid by using the Invalidate method, at which time, the callback procedure is again called and the return response is cached. The add-in or VBA macros can then force an immediate update of the UI by calling the Refresh method.
In your custom UI XML file you need to declare the onLoad callback:
<customUI … onLoad=”MyAddInInitialize” …>
And then in VBA you could use:
Dim MyRibbon As IRibbonUI
Sub MyAddInInitialize(Ribbon As IRibbonUI)
Set MyRibbon = Ribbon
End Sub
Sub myFunction()
‘ Invalidates the caches of all of this add-in’s controls
MyRibbon.Invalidate()
End Sub
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)
This is what I have so far but I'm still a novice.
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="OnRibbonLoad">
<ribbon>
<tabs>
<tab id="MyTools" label="Tools">
<group id="MoveGroup" label="Move" tag="GroupMove" >
<button id="MoveColumnLeft" tag="EnableLeft" imageMso="GoRtl" screentip="Move Column Left" supertip="Move the selected column to the left" label="Left" size="large" onAction="OnActionButton" getEnabled="GetEnabled" />
<button id="MoveColumnRight" tag="EnableRight" imageMso="GoLeftToRight" screentip="Move Column Right" supertip="Move the selected column to the right" label="Right" size="large" onAction="OnActionButton" getEnabled="GetEnabled" />
`<separator id="MoveSep" />`
<button id="MoveRowUp" tag="EnableUp" imageMso="MessagePrevious" screentip="Move Row Up" supertip="Move the selected row up" label="Up" size="large" onAction="OnActionButton" getEnabled="GetEnabled" />
<button id="MoveRowDown" tag="EnableDown" imageMso="MessageNext" screentip="Move Row Down" supertip="Move the selected row down" label="Down" size="large" onAction="OnActionButton" getEnabled="GetEnabled" />
</group>
</tab>
</tabs>
</ribbon>
</customUI>
Option Explicit
Public oRibbon As IRibbonUI, bEnabled As Boolean
Sub OnRibbonLoad(ribbon As IRibbonUI)
Set oRibbon = ribbon
bEnabled = True
End Sub
Sub OnActionButton(control As IRibbonControl)
Select Case control.ID
Case "MoveColumnLeft"
bEnabled = enabled
oRibbon.Invalidate
Case "MoveColumnRight"
bEnabled = enabled
oRibbon.Invalidate
End Select
End Sub
Sub GetEnabled(control As IRibbonControl, ByRef enabled)
`Select Case control.ID
Case "MoveColumnLeft"
enabled = enabled
Case "MoveColumnRight"
enabled = enabled
End Select
End Sub
How to create an access form which has two fields for importing two different excel files, and after selecting excel files press the button to run a query (already exist) and automatically export the query result in excel sheet. I was able to create the vba code (once played the import dialog will pop up waiting the user to enter the file path then pops up another time for the second file, another dialoge for exporting the result to excel. but the problem is how to do it using Forms in Microsoft Access.please give me suggestions or reference.
Agree with Boeckm, your question is a little lacking in detail :-)
If you are asking for the VBA code to fire the macro's you already have then simply create a button and add the following to the [on click] property
Private Sub Excel_button_Click(Cancel As Integer)
DoCmd.SetWarnings False ' Switch off "Are you sure" message
Dim stDocName As String
stDocName = "qry_Import file 1"
DoCmd.OpenQuery stDocName, acNormal, acEdit
stDocName = "qry_Import file 2"
DoCmd.OpenQuery stDocName, acNormal, acEdit
stDocName = "qry_Export file 3"
DoCmd.OpenQuery stDocName, acNormal, acEdit
DoCmd.SetWarnings True ' Switch on "Are you sure" message
End Sub
You can also build this in a single button using the wizzard (select misc, run query and select the first import query. Go back to the button and edit the [embedded macro] adding the others. You can also add the set warning = off to the series if required).
I have just added in Calendar 12.0 from the tools > Additional Controls. Calendar works fine and I have it spitting the date out to the right cells. What I would like, however, is to really make the calendar visible from a command button as my form contains a bunch of fields and I don't want to bog up the form with this calendar. I have tried Calendar1.show but the .show isn't an option.
So ultimately I need a command button to show the calendar, allow the user to select (I have that) and then close the calendar. Any help? I thank you in advance!!
bdubb
In this snippet, CommandButton1 is from the ActiveX controls, not the form controls. It requires that you click the button to show the calendar (which pops up next to the button you clicked), and click the button again to hide the calendar.
Private Sub CommandButton1_Click()
If Not Calendar1.Visible Then
Calendar1.LinkedCell = "A1"
Calendar1.Top = Sheet1.CommandButton1.Top
Calendar1.Left = Sheet1.CommandButton1.Left + Sheet1.CommandButton1.Width + 1
Calendar1.Visible = True
Else
Calendar1.Visible = False
End If
End Sub
Obviously, different buttons would require different linked cells, but it does mean that you could have a single calendar control that it displyed by multiple buttons (if that is what you want).
Unfortunately, it would appear that you cannot hide the control while any of its events are firing (e.g AfterUpdate). It just doesn't want to disappear!!
Hide/Close a calendar control still not works (new year 2015 = almost four years later) but I think I found a workaround to hide the control after firing events.
I have a Calendar1_AfterUpdate(), which launches before Calendar1_Click(). Code is placed directly in a worksheet and NOT in a module.
Private Sub Calendar1_AfterUpdate()
Range("a1") = Me.Calendar1.Value
' Next two lines does not work within AfterUpdate
' When running step by step it seems to work but the control is
' visible when End Sub has run
Me.Calendar1.Visible = True
Me.Calendar1.Visible = False
End Sub
To that I simply added
Private Sub Calendar1_Click()
Me.Calendar1.Visible = True
Me.Calendar1.Visible = False
End Sub
Please note that the control for some reason must be made visible before hiding.
Why it does not work directly in Calendar1_AfterUpdate() is a mystery to me.
Next problem is to hide the control when I remove the mouse. Mouse-events seems to be impossible in a calendar control ...