Making VBA Word add-in change the default RibbonUI tab - vba

(Be kind to me; I'm not a professional developer!)
I've created a custom Word ribbon with all sorts of business-specific functionality. I think it's awesome, but there are some old-school people here who want the built-in "Home" tab to show up by default because that's what they're "used to."
I added a menu option to change the default between the Home Tab and the HMF tab. The problem is that I can't actually figure out how to use the setting to change the active tab.
Here's a snippet of the ribbon code:
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="HMFRibbon.InitializeRibbon">
<ribbon>
<tabs>
<tab id="HMFTab" label="HMF" insertAfterQ="TabHome">
[...]
</tab>
</tabs>
</ribbon>
</customUI>
My STARTUP folder contains an "HMF_Toolbar.dotm" that includes the following code in the "HMFRibbon" module:
Public ribRibbon As IRibbonUI
Sub InitializeRibbon(ribbon As IRibbonUI)
On Error GoTo DefaultError
If GetSetting("HMFToolbar", "Defaults", "HMFIsDefault") = "False" Then
MsgBox ("Leaving 'Home' as default tab")
Else
Set ribRibbon = ribbon
MsgBox ("Activating 'HMFTab'")
ribRibbon.ActivateTab ("HMFTab")
End If
Exit Sub
DefaultError:
MsgBox ("Could not find default toolbar setting.")
End Sub
The code runs the first time a document is open, finds the right default and shows the right message, but doesn't actually change the starting tab to HMFTab. It also only runs when the ribbon is first opened, so even if it worked the first time it wouldn't run when subsequent documents were open (would would again default to "Home").
I tried moving the function to "AutoOpen()" in the HMFRibbon module, but that only fires if I open "HMFRibbon.dotm," not another document with the module loaded.
So... any ideas?
EDIT: I should have been clearer. By "default tab," what I really mean is that I want the ribbon to automatically activate either the "Home" or "HMF" tab depending on whether HMFIsDefault is true or false.
I've gotten closer by using the Application.AutoOpen function, but it fires before the ribbon is actually loaded, so "active doesn't work! Here's the code:
Option Explicit
Public WithEvents oApp As Word.Application
Private Sub oApp_DocumentOpen(ByVal Doc As Document)
On Error GoTo DefaultError
If GetSetting("HMFToolbar", "Defaults", "HMFIsDefault") = "False" Then
MsgBox ("Leaving 'Home' as default tab")
Else
MsgBox ("Activating 'HMFTab'")
HMFRibbon.ribRibbon.ActivateTab ("HMFTab")
End If
Exit Sub
DefaultError:
MsgBox ("Could not find default toolbar setting.")
End Sub

The IRibbonUI.ActivateTab method can be used for activating ribbon tabs. You just need to pass the Id of the custom Ribbon tab to be activated. You may also find the IRibbonUI.ActivateTabMso method for built controls and IRibbonUI.ActivateTabQ which uses the fully qualified name of the tab, which includes the ID and the namespace of the tab.
You may consider using the insertAfterMso attribute for the custom ribbon tab if you want to place it after a specific built-in ribbon tab.
Compare the following attributes:
insertAfterMso - Specifies the identifier for the built-in control after which to position this control.
insertAfterQ - Specifies the identifier of a qualified control (that is, a control whose idQ property was specified) after which to position this control.
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

How to use Events with Option Button Controls on Userform [duplicate]

This question already has answers here:
Assign code to a button created dynamically
(2 answers)
Closed 4 years ago.
I am trying to add an option button from the range in the Excel worksheet.
For Each Value In OptionList
Set opt = UserForm3.Controls.Add("Forms.OptionButton.1", "radioBtn" & i, True)
opt.Caption = Value
opt.Top = opt.Height * i
opt.GroupName = "Options"
UserForm3.Width = opt.Width
UserForm3.Height = opt.Height * (i + 2)
i = i + 1
Next
I want to create an event handler so that if radiobtn1 is selected while running the code from the user. Alhough I got a lot of answers, those are meant for worksheet user form.
My intention is to work on the VBA user form. Please help me with your thoughts.
There is only one type of userform, however there is [eternal] confusion surrounding the two types of controls available to Excel — exacerbated by the contrasting terminology used by different online sources. (Only the sections about ActiveX controls apply to userforms.) Perhaps I can help shed some light by putting it in words that help me understand. ☺
Overview:
There are two types of controls: Form controls and ActiveX controls:
Both types of controls can be used on worksheets but only ActiveX controls can be used on userforms.
Form controls are part of the Shapes collection (just like Drawing Objects), and thus are referred to like:
ActiveX controls are basically part of the worksheet and are therefore referred to like:
Both types of controls can be created, modified and deleted from either the worksheet, or programmatically with VBA, however, the 2 types of controls have slightly varying syntax when using VBA to refer to them.
Some sites discuss also discuss a Data Form. This is nothing more than a userform made specifically for data entry/manipulation of data, so it would've made more sense to call them (the more familiar sounding) "Data Entry Userform".
Office documentation also occasionally refers to a worksheet as a form. While this is technically correct, don't let this confuse you. Think of the word "form" as being used in a general sense:
Two Types of Controls
Form Controls
ActiveX Controls
The two look, behave, and are controlled similarly, but not identically. (List here.)
For example, let's compare the two types of Combo Boxes. In some programming languages, comparable controls are referred to as a "drop-down menu" or "drop-down list". In Excel, we have a "Form Control Combo Box", and an "ActiveX Control Combo Box":
(Click image to enlarge.)
☆ "Default name" applies to controls created manually. Controls created programmatically do not have (or require) a default name and therefore should have one assigned immediately upon creation.
(Source: my answer)
About ActiveX controls and related security concerns
An ActiveX control is an extension to the VBA Toolbox. You use ActiveX controls just as you would any of the standard built-in controls, such as the CheckBox control. When you add an ActiveX control to an application, it becomes part of the development and run-time environment and provides new functionality for your application.
An ActiveX control is implemented as an in-process server (typically a small object) that can be used in any OLE container. Note that the full functionality of an ActiveX control is available only when used within an OLE container designed to be aware of ActiveX controls.
This container type, called a control container or control object, can operate an ActiveX control by using the control’s properties and methods, and receives notifications from the ActiveX control in the form of events. The following figure demonstrates this interaction:
(Source: this and this)
See also:
Wikipedia: ActiveX
Symantec.com : Discussion of ActiveX Vulnerabilities
How-To Geek : What ActiveX Controls Are and Why They’re Dangerous
Option Buttons (Radio Buttons)
In Excel, the two types of radio buttons are actually called Option Buttons. To further confuse matters:
the default name for the form control is OptionButton1.
the default name for the ActiveX control is Option Button 1.
A good way to distinguish them is by opening the control's Properties list (on the ribbon under the Development tab, or by right-clicking the control and choosing Properties, or hitting F4), because the ActiveX control has many more options that the simpler form control.
Option buttons and checkboxes can be bound together (so only one option at a time can be selected from the group) by placing them in a shared Group Box.
Select the group box control and then hold Ctrl while selecting each of the other controls that you want to group. Right-click the group box control and choose Grouping → Group.
The first two links below are separate sets of instructions for handling each type of option button.
HANDLING CONTROL EVENTS:
Form control events (Click event only)
Form control events are only able to respond to one event: the Click event. (More info here.) Note that this section doesn't apply to userforms since they use only ActiveX controls.
To add a procedure for the Click event:
Right-click the control and choose Assign Macro...
In the 'Assign Macro` Dialog:
Select an existing procedure, and click OK, or,
Create a new procedure in the VBE by clicking New..., or,
Record a new macro by clicking Record..., or,
to Remove the assigned event, delete its name from Macro Name field and click OK.
(Click image to enlarge.)
To rename, edit or delete existing macros, hit Alt+F8 to open the Macro interface:
ActiveX control events
ActiveX controls have a more extensive list of events to which they can be set up to respond.
To assign events to ActiveX controls, right-click the control and choose View Code. In the VBE, you can paste in code, or choose specific events from the drop-down list at the top-right of the VBE window.
(Click image to enlarge.)
Control event handling on a userform:
Events can also be used in controls on userforms. Since only ActiveX controls can be placed a userform, you'll have the "more coding + more functionality" trade-off.
ActiveX controls are added to userforms the same way as they are added to a worksheet. Keep in mind that any events assigned to the userform itself (ie., background) will be "blocked" in any areas covered up by a control, so you may need to assign the same events to the controls as well as the userform.
For example, in order to make this userform respond to MouseMove anywhere on the form, the same event code was applied to the userform, textboxes, option buttons and the frame:
VBA EXAMPLES
Add/Modify/Delete a form control option button using VBA:
Sub formControl_add()
'create form control
Dim ws As Worksheet: Set ws = ActiveSheet
With ws.Shapes.AddFormControl(xlOptionButton, 25, 25, 100, 100)
.Name = "cOptionButton1" 'name control immediately (so we can find it later)
End With
End Sub
Sub formControl_modify()
'modify form control's properties
Dim ws As Worksheet: Set ws = ActiveSheet
ws.Shapes("cOptionButton1").Select
With Selection 'shapes must be Selected before changing
.Characters.Text = "wxyzabcd"
End With
End Sub
Sub formControl_delete()
'delete form control
Dim ws As Worksheet: Set ws = ActiveSheet
ws.Shapes("cOptionButton1").Delete
End Sub
Shapes.AddShape Method (Excel)
Shape Properties (Excel)
Characters Object (Excel)
Add/Modify/Delete an ActiveX command button using VBA:
Sub activexControl_add()
'create ActiveX control
Dim ws As Worksheet: Set ws = ActiveSheet
With ws.OLEObjects.Add("Forms.CommandButton.1")
.Left = 25
.Top = 25
.Width = 75
.Height = 75
.Name = "xCommandButton1" 'name control immediately (so we can find it later)
End With
End Sub
Sub activexControl_modify()
' modify activeX control's properties
Dim ws As Worksheet: Set ws = ActiveSheet
With ws.OLEObjects("xCommandButton1").Object
.Caption = "abcxyz"
.BackColor = vbGreen
End With
End Sub
Sub activexControl_delete()
' delete activeX control
Dim ws As Worksheet: Set ws = ActiveSheet
ws.OLEObjects("xCommandButton1").Delete
End Sub
OLEObjects.Add Method (Excel)
BackColor, ForeColor Properties (ActiveX Controls)
Add/Remove items from a form control combo box:
Sub ComboBox_addRemoveItems_FormControl()
Dim ws As Worksheet: Set ws = ActiveSheet
'add item to form control combo box
ActiveWorkbook.Sheets("Sheet1").Shapes("Drop Down 1").ControlFormat.AddItem "abcd"
'remove all items from from form control combo bo
ActiveWorkbook.Sheets("Sheet1").Shapes("Drop Down 1").ControlFormat.RemoveAllItems
End Sub
Add/Remove items from an ActiveX combo box:
Sub ComboBox_addRemoveItems_ActiveXControl()
Dim ws As Worksheet: Set ws = ActiveSheet
'add items to ActiveX combo box
ActiveWorkbook.Sheets("Sheet1").ComboBox1.AddItem "abcd"
'remove all items from ActiveX combo box
ActiveWorkbook.Sheets("Sheet1").ComboBox1.Clear
End Sub
More Information:
Office.com : Add a checkbox or option button (Form controls)
Office.com : Add a checkbox, option button, or toggle button (ActiveX controls)
Office.com : Overview of forms, Form controls, and ActiveX controls on a worksheet
Office.com : Enable selection through choice controls (check and list boxes)
Office.com : Add, edit, find, and delete rows by using a data form
MSDN : VBA Shape Members
MSDN : Using ActiveX Controls on Sheets (Office)
Exceldemy : How to Use Form Controls in Excel
MSDN : Using Windows Forms Controls on Excel Worksheets (Visual Studio)
Microsoft TechNet : Behaviour of ActiveX controls embedded in Office documents

Disable File>Share in Excel with VBA

I need a way to disable the ability for a user to go to (or use) the menu File > Share
I have similar for other save commands like below but need something for this feature as well
Application.CommandBars("Worksheet Menu Bar").Controls("File").Controls("Save As...").Enabled = False
Application.CommandBars("Worksheet Menu Bar").Controls("File").Controls("Save").Enabled = False
I have tried:
Application.CommandBars("Worksheet Menu Bar").Controls("File").Controls("Share").Enabled = False
to no avail
My aim is to stop users saving copies of this file (Hosted on a server), I fully understand Excel isn't meant to be secure and there is always a way to do this but want to make it as hard as I can for the average Joe
Regards
You could use a for each loop to extract the available commands:
' Iterate available commands from the file command bar.
Sub PrintAllCommandBarControlNames()
Dim cbControl As CommandBarControl
For Each cbControl In Application.CommandBars("Worksheet Menu Bar").Controls("File").Controls
Debug.Print cbControl.Caption
Next
End Sub
Run on Excel 2010, I couldn't find a share option. Might just be my system. The above returned:
&New...
&Open...
&Close
&Save
Save &As...
Single Web Page (*.mht)
Save &Workspace...
File Searc&h...
Per&mission...
Per&mission
Ch&eck Out
Ch&eck In...
Ve&rsion History...
We&b Page Preview
Page Set&up...
Prin&t Area
Print Pre&view
&Print...
Sen&d To
Propert&ies
&Recent File Name Goes Here
&Recent File Name Goes Here
Sign ou&t
E&xit Excel
The 'backstage' menu (that you get when you click top left File menu) is effectively part of the Ribbon, and not a Command Bar. If you tried disabling Save for instance, using your example, you'll find they don't work on 2010/2013 etc.
There is this answer which tells you how to manipulate those menu items in the ribbon: Remove "Save & Send" from File menu in Excel 2010 using custom XML and one of the items is called TabShare.

Word 2013 - Macro Reference in .docx file

I have a pretty large template (in terms of macros) and I've created a new module that is called when the user does a specified shortcut on the keyboard.
The Macro does nothing more but call "ThisDocument.HideComboBoxes".
"HideComboBoxes" is a Sub in ThisDocument, which does the obvious: hide all combo boxes in the document.
The code works fine as long as I'm working with the template.
If I render a new document out of it (a docx file) the shortcut does not work anymore (which is kinda obvious because the ThisDocument is now empty for the document).
How do I access the template's ThisDocument from within the document or how can I hide the combo boxes from within the docx?
Here's the code for hiding the comboboxes in the template's ThisDocument:
Sub HideComboBoxes()
Me.ComboBoxConfi.Width = 1
Me.ComboBoxConfi.Height = 1
Me.ComboBoxState.Width = 1
Me.ComboBoxState.Height = 1
End Sub
Thanks in advance
You need to put the code in a "normal" module. This will require changing the calls to the ActiveX controls, which is a pain, but works.
Assuming the ActiveX controls are managed on the document surface as InlineShapes a call would look like this:
Dim cbConfi as Object 'or as MsForms.ComboBox to get Intellisense
Set cbConfi = ActiveDocument.InlineShapes([indexvalue]).OLEFormat.Object
cbConfi.Width = 1
If you don't want to rely on the index value (position of the control in the InlineShapes collection) you can select the ActiveX control and assign a bookmark to it. Or you can loop the collection of ActiveX controls, check the Type and, if it's a OLE object, check whether the Class type is MSForms.Combobox and then via OLEFormat.Object.Name whether its the right one.

Activate a particular Ribbon Tab

I've seen lots of code for how to ActivateTab OnLoad but can't get it to work dynamically... on the click of a worksheet button for example.
There is a button on Sheet1 pointing at startHereConfigure
<customUI onLoad="RibbonOnLoad"
xmlns="http://schemas.microsoft.com/office/2009/07/customui">
Public Rib As IRibbonUI
Sub RibbonOnLoad(ribbon As IRibbonUI)
Set Rib = ribbon
End Sub
Sub startHereConfigure()
Rib.ActivateTab "Configure"
End Sub
I want to be able to call startHereConfigure (and other similar subs) to bring to the fore a particular Tab - how do I do this?
Add this line to the custom XML file:
<customUI onLoad="RibbonOnLoad" xmlns="http://schemas.microsoft.com/office/2009/07/customui">
Where "RibbonOnLoad" is the name of the function to be called upon starting Outlook.
Add this funciotn into a standard module:
Public Rib As IRibbonUI
Sub RibbonOnLoad(ribbon As IRibbonUI)
Set Rib = ribbon
Rib.ActivateTab "Configure" ' Name of the tab to activate
End Sub
Jorge's answer is the normal way.
I introduce 2 other work-arounds here.
One is moving your custom tab control before the Home Tab
by adding 'insertBeforeMso' in your customui(14).XML.
<tab id="id1" label="Tab1" insertBeforeMso="TabHome">
Your 'Tab1' is the first one, so it is activated first when opening your office file.
The other one is using SendKey method which is a little tricky.
After adding onLoad macro in customui XML,
you can add following lines in a module in VBE.
Sub onLoad(control As IRibbonUI)
'control.ActivateTab "Tab1"
Application.SendKeys "%Y%" 'Alt + Y + Alt key
End Sub
Here 'Y' key is your custom tab shortcut key and 'Alt' key is sent again after 'Y' key in order to prevent the Alt shortcut keys from appearing on ribbon menus.
Samuel Liew: I thought the way I answered was implicit enough.
The following is the same expanded to be more explicit:
Sean: Unclear from the above if you got an answer or you solved it yourself.
As, I can't see an answer and your last comment suggests you went off with false information.
Certainly your code should work in 2010 office systems.
I'm doing just that and activating a range of different tabs, based on targeted worksheet 'types' becoming active. And the tab activation code is just part of a general workbook events handling sub (i.e. called by application event handlers).
And that has been operational since prior to you asking this question.
So the response from Siddharth Rout above about not being able to do this is invalid.
I'm assuming your Tab id is defined in the xml to match the id in your code above per:
<tab id="Configure" label="YOUR LABEL" >
I'm also assuming the rest of your xml is correct, and you can see the tab, just not be able to activate it.
If all that's the case, as to 'How to': You should just need to call that sub.
In my case I do that on Workbook or Worksheet activated (on open or change of window). But any call mechanic (such as your in-sheet control) should work just as well.
As an aside, I'd recommend using more obviously unique codes for ribbon control ids
e.g. Using some leading chars from the overall function and the control type like 'xyzTab_Configure'.
Just means if/when you add more, you have a explicit way to know which is which, and avoid any clashes.
That all covered: I have however run into an issue with office 2019.
See: vba IRibbonUI.ActivateTab not working in Office 2019

How to use VBA to read text entered in an editBox on a custom Ribbon tab?

I have added a tab to the Ribbon in MS Project 2010 using the SetCustomUI VBA method as detailed here: http://msdn.microsoft.com/en-us/library/ee767705.
The tab XML loads fine and the layout is set up properly. The problem is when executing the VBA callbacks associated with my buttons and editBoxes, Project does not seem to be using the standard method signatures defined here: http://msdn.microsoft.com/en-us/library/aa722523.aspx#a16c7df5-93f3-4920-baa8-7b7290794c15_Ribbon.
These signatures work in the "more standard" Office programs like Excel 2010, but when I write the methods with the same parameters in Project, I get exception pop-ups unless I remove all parameters from the method. This is okay for buttons (which are demonstrated in the first MSDN article), but for the "onChange" callback for editBoxes, with no arguments provided in the callback, I have no way to read what text has been entered in the editBox, making them useless. How is the content of a Ribbon editBox supposed to be accessed in Project? Has VBA access to this String just been overlooked in Project? Can it only be accessed with Managed Code?
Here's an example of an XML / VBA pair I've tried:
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
<ribbon >
<tabs >
<tab
id="NavHelper"
label="Nav Helper">
<group
id="Group1"
label="Search">
<box id="Box1" >
<editBox
id="DateBegin"
label="Dates from"
sizeString="11/11/1111"
onChange="DateBegin_onChange"/>
<editBox
id="DateEnd"
label="to"
sizeString="11/11/1111"
onChange="DateEnd_onChange"/>
</box >
<button
id="doSearch"
imageMso="InstantSearch"
label="Search"
size="large"
onAction="doSearch_onAction"/>
</group >
</tab >
</tabs >
</ribbon >
</customUI >
And the VBA:
Public Sub DateBegin_onChange(control As IRibbonControl, text As String)
MsgBox text
End Sub
Public Sub doSearch_onAction(control As IRibbonControl)
MsgBox "pressed!"
End Sub
So with this example, the set up works perfectly in Excel, but if I bring it to Project, the callbacks won't run unless I remove all of the parameters from the method definitions, at which point they run, but are useless. Any ideas?
Have you tried the Custom UI Editor for Microsoft Office?
See http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2009/08/06/7293.aspx
I haven't worked in MS Project, but in the other office programs you can enter the customUI XML and validate it and also get the corresponding VBA-function signatures.
If I try your customUI XML in Excel and try to validate (I don't have Project...), I get an error saying the namespace is wrong.