I did a program that I wished to distribute to my co-workers, they are not VBA oriented. So I wish to distribute it easily.
I created an Add-in, when install the add-in needs to create a custom Ribbon. I tried my best, but I cannot find easy to understand documentation.
My code is as follow :
Private Sub Workbook_AddinInstall()
On Error Resume Next 'Just in case
Application.CommandBars("Worksheet Menu Bar").Controls("Super Code").Delete
Set cControl = Application.CommandBars("Worksheet Menu Bar").Controls.Add
With cControl
.Caption = "Open SCF workbook"
.Style = msoButtonIconAndCaptionBelow
.OnAction = "OpenTheCorrectFile"
.FaceId = 7720
.DescriptionText = "Open the SCF workbook"
End With
Set cControl = Application.CommandBars("Worksheet Menu Bar").Controls.Add
With cControl
.Caption = "Are they onboard"
.Style = msoButtonIconAndCaptionBelow
.FaceId = 5817
.OnAction = "Check_Suppliers_Already_On_Board"
.DescriptionText = "Check if suppliers have already been on boarded"
End With
End Sub
Now if you use my code you will notice that:
Buttons are small
Icons are small
No description when hoovering them
No special name for the new ribbon, it is call Add-ins
No special name for this group, it is call "Menu Commands"
Does anyone know how to solve this.
Whenever I am looking for those answer people are using special application to create the ribbons, I do not wish to do it. I am also a beginner in VBA, so everything that is easily digestible is welcome.
Thank you very much.
Here's an example of how you can do it without using any external application, just a text editor. But you will have to be careful to write XML code properly, or the excel file may not open correctly (make a backup copy).
You will create a folder named "customUI" and, inside that folder, a file named "customUI.xml"
You will write all your Ribbon details inside "customUI.xml". I wrote this example, covering the issues you listed: Big buttons and icons (Images list in https://bert-toolkit.com/imagemso-list.html) / Tooltip description (screentip and supertip) / Ribbon name (tab label) / Group names (group labels)
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
<ribbon>
<tabs>
<tab id="CustomTab" label="Add-ins">
<group id="Group1" label="Menu Commands">
<button id="Button1" label="Happy" size="large" screentip="Test1" supertip="Test1 description" imageMso="HappyFace" onAction="Macro1" />
<button id="Button2" label="Save" size="large" imageMso="FileSave" onAction="Macro2" />
<button id="Button3" label="{a}" size="large" imageMso="FieldCodes" onAction="Macro3" />
</group >
<group id="Group2" label="Other Commands">
<button id="Button4" label="Reply" size="large" imageMso="Reply" onAction="Macro4" />
</group >
</tab>
</tabs>
</ribbon>
</customUI>
Rename your .XLSM file to .ZIP, then you will be able to edit/add files. Add the customUI folder to the zip file.
From the ZIP file, extract the .rels file that is inside _rels folder, you will add this line between the last Relationship tag and the Relationships closing tag, and then put it back inside the ZIP file overwriting the .rels file there
<Relationship Id="someID" Type="http://schemas.microsoft.com/office/2006/relationships/ui/extensibility" Target="customUI/customUI.xml" />
Rename the file back to .XLSM and open it, if everything is right, the new Ribbon will be there. It's important that the macros that will be called by the buttons have a control parameter, like this:
Sub Macro3(ByVal control As IRibbonControl)
That's it, everything about the UI is in the customUI.xml file, there is no more adding buttons in VBA. If you have to change something in the UI, you will have to rename it to ZIP again, overwrite the customUI.xml file and rename to XLSM again. Here's the Ribbon I got in this example:
Related
I have a Word VBA Template that accomodates Old and New Versions. Posted below accomodates the old style. The new one is an Add In that works fine as well. The problem is simply that the customized menus work when right clicking outside an inserted table but not when right clicking inside it. PS: I actually don't think posting this code is really necessary because It seems that customized menus don't work inside a table.
Public Sub BuildCustomMenus2()
On Error Resume Next
With Application.CommandBars("Menu Bar")
.Controls("rate1").Delete
End With
Dim aVal As Single
aVal = ToDoubleFromString(Application.Version)
If aVal < 12 Or Trim$(GetSetting("rate1", "Narrative Software", "NoWordRibbon")) = "Yes" Then
If ThisDocument.Application.Windows.count > 0 Then SetN1Defaults
Dim vCtrlCount As Integer
Dim ctrlControl As CommandBarControl
'delete any previously created custom toolbars and rebuild
On Error Resume Next
With Application.CommandBars("Menu Bar")
.Controls("rate1").Delete
End With
vCtrlCount = CommandBars("Menu Bar").Controls.count
vCtrlCount = vCtrlCount + 1
With CommandBars("Menu Bar").Controls
.Add(Type:=msoControlPopup, BEFORE:=vCtrlCount).Caption = "&rate1"
End With
'add more macros to options here...and create
'sub...add to select case statement
'1. Add the buttons
'2. title caption
'3. Display only the caption text
'4. call procedure to pass button call
Set ctrlControl = CommandBars("Menu Bar").Controls("rate1").Controls.Add(msoControlButton)
ctrlControl.Caption = "Navigate"
ctrlControl.Style = msoButtonIconAndCaption
ctrlControl.OnAction = "RunDocMap"
ctrlControl.FaceId = 1714
Set ctrlControl = CommandBars("Menu Bar").Controls("rate1").Controls.Add(msoControlButton)
ctrlControl.Caption = "Mark Active Edit"
ctrlControl.Style = msoButtonIconAndCaption
ctrlControl.OnAction = "MarkActiveEdit"
ctrlControl.FaceId = 279
Set ctrlControl = CommandBars("Menu Bar").Controls("rate1").Controls.Add(msoControlButton)
ctrlControl.Caption = "Go to Active Edit"
ctrlControl.Style = msoButtonIconAndCaption
ctrlControl.OnAction = "GoToActiveEdit"
ctrlControl.FaceId = 39
End Sub
Prior to Microsoft Office 2010, the only way to customize context (right-click) menus in the Microsoft Office Fluent Ribbon user interface (UI) was by using CommandBars solutions. In Office 2010, you can customize built-in context menus just as you can the other components of the Ribbon UI. This XML-based context menu extensibility model is based on the familiar Ribbon extensibility model. This means that you can use the same XML markup and callbacks that you currently use to customize the Ribbon UI.
Command bars were deprecated with MS Office 2010. Use the Fluent UI (aka Ribbon UI) for customizing context menus in Office 2010 and later. See Customizing Context Menus in Office 2010 for more information. For example:
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
<contextMenus>
<contextMenu idMso="ContextMenuText">
<button idMso="FontDialog" visible="false" />
<toggleButton id="MyToggle" label="My Toggle Button" />
<button id="MyButton" label="My Button" insertBeforeMso="HyperlinkInsert" onAction="GetButtonID" />
<menuSeparator id="MySeparator" />
<menu id="MySubMenu" label="My Submenu" >
<button id="MyButton2" label="Button on submenu" />
</menu>
<gallery id="galleryOne" label="My Gallery">
<item id="item1" imageMso="HappyFace" />
<item id="item2" imageMso="HappyFace" />
<item id="item3" imageMso="HappyFace" />
<item id="item4" imageMso="HappyFace" />
</gallery>
<dynamicMenu id="MyDynamicMenu" label= "My Dynamic Menu" getContent="GetMyContent" />
</contextMenu>
</contextMenus>
</customUI>
If the table is an embedded OLE object (Excel worksheet) you need to customize the context menu in Excel in that case.
I created a custom ribbon using Custom UI Editor For Microsoft Office
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
<ribbon>
<tabs>
<tab idMso="TabHome" >
<group id="customGroup1" label="My Group" insertAfterMso="GroupEditingExcel">
<button id="customButton1" label="Click Me" size="large" onAction="test()" imageMso="HappyFace" />
</group>
</tab>
</tabs>
</ribbon>
</customUI>
I saved excel 2007 file as Excel Macro-Enabled workbook
Here is my macro. It works fine when it run manually
Sub test()
For i = 1 To 10
For j = 1 To i
Cells(i, j) = j
Next
Next
End Sub
But When I press the smiling face button in my custom ribbon it gives following error message.
cannot run the macro 'test()' the macro may not be available in this
workbook or all macro may be disabled.
How can I fix this issue ? Any suggestions ?
Thank you
You should not include the brackets. So change this:
onAction="test()"
to:
onAction="test"
Also, make sure the routine name is unique and does not exist in any other workbook you might have open in Excel, otherwise you risk the wrong routine being called.
I am trying to add an extra tab to the Word ribbon and have a couple buttons to invoke my own macros. I did the same thing with Excel and it worked fine. For some reason I can't get it to work in Word. I am using the Custom UI Editor. Here's the ribbon code.
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
<ribbon startFromScratch="false">
<tabs>
<tab id="customTab" label="Pavel">
<group id="customGroup" label="Formatting">
<button id="customButton" label="Custom Button" imageMso="HappyFace" size="large" onAction="Callback" />
</group>
</tab>
</tabs>
</ribbon>
</customUI>
Just a very simple tab, with one button that calls the macro Callback().
I added a module to the Word file with the following code.
Sub Callback()
MsgBox ("Test")
End Sub
The macro runs fine on its one (hitting the play button in the editor) but when invoked via the button on the tab I get the following error:
Edit: It seems to do something with 1) public access to the module and 2) apparently the macro should be taking some argument similar to "control as ribboncontrol" or something like that. If you know where to find the documentation for this, please let me know.
A Ribbon button expects a Sub which takes a parameter:
Sub Callback(button As IRibbonControl)
MsgBox ("Test")
End Sub
http://msdn.microsoft.com/en-us/magazine/cc163469.aspx
I am developing a custom ribbon extension for Excel, in which a control requires different custom images. I managed to use some images located in my filesystem, but I would like to embed these images inside the .xlsm file.
Is it possible to do it and to reference them from the VBA code that updates the image of the control?
For test purposes, this is the XML that defines my custom ribbon:
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="ribbonLoaded">
<ribbon>
<tabs>
<tab idMso="TabHome" >
<group id="customGroup1" label="My Group" insertAfterMso="GroupFont">
<button id="customButton1" label="Click Me" size="large" onAction="Macro1" getImage="getButtonImage"/>
</group>
</tab>
</tabs>
</ribbon>
</customUI>
And this is the macro that change the image of the customButton1 control:
Dim imgIndex As Long
Public Sub getButtonImage(ByVal control As IRibbonControl, ByRef Image)
Select Case control.ID
Case "customButton1"
Set Image = LoadPicture("img" + Trim(Str(imgIndex)) + ".bmp")
imgIndex = (imgIndex + 1) Mod 2
End Select
End Sub
I tried to add the bmp files inside the .xlsm and reference them updating the relationships file (.rels), but I don't know how to reference them from VBA and most important, when I open the file with Excel and save it, they are automatically deleted...
Any help is appreciated!
If the image is embedded in the customUI, you do not need VBA to add them to a control. Just use the same ID for the image in an image tag:
<button id="button1" label="Test" size="large" image="TestID" onAction="ButtonOnAction" />
My sample is adressing the image with ID "TestID", which must be found in the customUI XML - expand the customUI node in the Custom UI Editor to find or change the image ID (or use the editor to add a new image).
robcooper's answer from UtterAccess.com might help:
Public Sub getButtonImage(ByVal control As IRibbonControl, ByRef image)
'for use in Access 2007 Ribbon control
'requires a reference to the Micrsoft Office 12.0 Object Library
Select Case control.ID
Case "cmdMainMenu"
Set image = LoadPicture(CurrentProject.Path & "\home.bmp")
End Select
End Sub
I am trying to dynamically add a new custom ribbon in a Word 2007 document following teh manual method described in this article :- http://msdn.microsoft.com/en-us/library/aa338202(v=office.12).aspx.
The article specifies the following :-
a) Create a XML file named customUI.xml which will contain the elements you want to display
in the tab and put the same in a folder named customUI.
b) Rename your Word 2007 document to .zip. Add the above "customUI" folder to the zip file.
c) Add the following relationship to the "_rels/rels" file in the .zip file :-
<Relationship Type="http://schemas.microsoft.com/office/2006/
relationships/ui/extensibility" Target="/customUI/customUI.xml"
Id="customUIRelID" />
Do we have some code sample to achieve the same using OpenXML SDK? For example, how to add the "RibbonExtensibilityPart" (which contains the ribbon XML) to the document?
EDIT :-
This is how I did the above mentioned steps:-
string documentFileName = <path of the docx file>;
string ribbonXml = <path of the ribbon XML file>;
using (WordprocessingDocument myDoc = WordprocessingDocument.Open(documentFileName, true))
{
MainDocumentPart mainPart = myDoc.MainDocumentPart;
if (myDoc.GetPartsCountOfType<RibbonExtensibilityPart>() > 0)
myDoc.DeletePart(myDoc.GetPartsOfType<RibbonExtensibilityPart>().First());
RibbonExtensibilityPart ribbonExtensibilityPart = myDoc.AddNewPart<RibbonExtensibilityPart>();
ribbonExtensibilityPart.CustomUI = new DocumentFormat.OpenXml.Office.CustomUI.CustomUI(File.ReadAllText(ribbonXML));
myDoc.CreateRelationshipToPart(ribbonExtensibilityPart);
}
and I am able to see the new ribbon with the elements in it.
However, I have buttons in the ribbon and I want to add handle actions on those buttons. Following is what my Ribbon XML looks like :-
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
<ribbon>
<tabs>
<tab id="CustomTab" label="My Tab">
<group id="MyGroup" label="My Group" >
<button id="Button1" label="My Large Button"
size="large"/>
<button id="Button2" label="My Normal Button"
size="normal" *onAction="ThisDocument.MyOtherButtonMacro"* />
</group >
</tab>
</tabs>
</ribbon>
</customUI>
have a look at the "onAction="ThisDocument.MyOtherButtonMacro". I know I can write Macro function in the document. However, as the custom ribbon will be added dynamically on the server-side, I am not sure how I can add the macro dynamically. Could anyone help?