RibbonCustomizer™
Customize your Office 2007 Ribbon (Office Fluent™)with only a few mouse clicks! Works with Microsoft® Access™, Excel®, Outlook®, PowerPoint® and Word 2007.

Buy for $29.99

Download free Starter Edition

Subscribe | Subscribe by Email |

Categories

Archive


“Hello World” in Access, Excel, PowerPoint and Word from a COM Add-In using .NET (C#) - Word StyleChooser

June 14th, 2006 by Patrick Schmid

If you are not interested in the implementation details, you can download the Word StyleChooser add-in directly. If you installed an earlier version this morning, please uninstall that one first. I made a few changes to have the add-in behave nicer. Please note that you need to open the zip file and run setup.exe from there.
I had originally planned to do another “Hello World” example to cover COM Add-Ins, but I decided to rather do something more useful. The example I am going to do here is going to be for Word only. It is going to implement a sorely missing functionality in Word 2007, namely a simply combo box to see the current style and choose another one. Microsoft provides the style gallery and style task pane, but neither one is really useful to heavy users of Word styles. All the RibbonX related topics I will discuss in this example can be transferred straight to Access, Excel and PowerPoint. Outlook has some peculiarities which I will discuss in separate post. Let me apologize to most of you for using C# here. I installed a 400 GB hard drive in my desktop today and currently all my data is being copied over. Unfortunately the hard drive on my Tablet PC has only 40 GB and wasn’t big enough to support C# and VB.NET, which is why I ended up installing only C# (my preferred language). A 100 GB hard drive for my tablet to address this issue arrived today as well, but this will have to wait until my desktop is usable again. I’ll provide the VB.NET source code for this example soon.

For this post, I am going to assume that you know how to create a COM Add-In for Office using Visual Studio .NET. If you don’t know how to do that, consult the Visual Studio help, the MSDN library, an Office programming book or search on Google. I will use Visual Studio .NET 2003.

Getting started

I am going to call this add-in StyleChooser and using the Visual Studio Add-In Wizard, I am making it a Microsoft Word add-in with the full name of “Microsoft Word 2007 StyleChooser Add-In”. In VS 2003, I need to add a reference to the Word 12 PIA as well as the Office 12 Object Library. The Office Object Library reference that the VS add-in wizard added needs to be removed. The Word 12 PIA can be found under the .NET tab and is called “Microsoft.Office.Interop.Word” with the version 12.0.0.0. The Office 12 Object Library can be found under the COM tab and is called “Microsoft Office 12.0 Object Library” with the version 2.4. With these references, the add-in will now load correctly in Word 2007.

Determining the version of Word

The add-in will not only load in Word 2007, but also Word 2003 (I don’t have any earlier Office version so I don’t know if it will load in those as well). As it is specifically geared to 2007 though, there is no point in having the add-in loaded in 2003 as well. For the user, that would be just a waste of memory. Note that the add-in will correctly load in 2003, but do nothing, as 2003 does not retrieve the RibbonX code from the add-in. This is important to know when you want to write an add-in that displays a UI in 2003 and 2007. If it is being loaded in 2003, you need to push the UI to Office. If it is being loaded in 2007, Office will pull the UI from the add-in.

In order to be nice to the user, we should therefore automatically unload the add-in if it is not loaded in Word 2007 (or any later version). We can determine the current version in the OnConnection method. As publishing code via the Word blogging feature isn’t simple, I am not going to show code in the example, but rather refer you to the C# source code file. The version can be determined using the Application.Version method. This returns a string which isn’t necessarily a number. My own add-in in fact kept crashing with Access 2007 B1TR until I realized that the version string returned by Access included the word “Beta” after the version number. Hence the code tries to strip out anything but the major version number (12) and catches any error the number conversion might trigger.

If the add-in is not loaded in Word 2007, it unloads itself using the Microsoft.Office.Core.COMAddIn.Connect value (setting it equal to false).

The code so far loads the add-in into Word 2007 and unloads it if an earlier version is detected. With only this rudimentary code, the add-in can be installed into Word and its presence can be checked via Word Options, Add-Ins.

While developing a COM Add-in, you probably want to run it in debugging mode, which means you want to hit Run in Visual Studio which should then open Word and give you the full VS debugging options for it. If you are, like me, using VS 2003, this won’t work if you have the .NET 2.0 Framework installed. The only currently known workaround for this issue is to uninstall the 2.0 Framework. Microsoft has yet to find a better workaround.

Loading the RibbonX code

In order to load RibbonX code, the add-in needs to implement the IRibbonExtensibility interface. This interface requires the implementation of the string GetCustomUI(string) method. The string argument that is passed to GetCustomUI contains the ribbon ID. You can ignore this argument for Access, Excel, PPT and Word. I will discuss its significance with Outlook.

GetCustomUI needs to return the full RibbonX code as string. In contrast to VBA this allows you to dynamically create the RibbonX code you are returning to Office. I personally prefer to store the entire XML code as a resource file in the add-in instead of some long and cumbersome string in the code. Therefore I added an XML file called RibbonX.xml to the project (make sure to set its build action to “embedded resource”). The code to get the XML from that embedded resource can be found in the GetCustomUI method. The most noteworthy thing here is the string attribute of the System.Reflection.Assembly.GetManifestResourceStream(string) method. It needs to include your add-in name as well as the full file name. In my example it is “StyleChooser.RibbonX.xml”. You should always verify that your resource file is actually being loaded. If you have trouble figuring out the correct parameter, use the code I commented out. I should also tell you that at least with VS 2003, the RibbonX.xml will not be recompiled unless you use “Rebuild Solution”. This means, if you make a change to the file and use “Build Solution”, the change won’t be compiled into your add-in and you’ll be wondering what is going on. Therefore, if you change anything in the embedded RibbonX file, rebuild the solution always.

RibbonX code

The RibbonX code for this example is going to be simple. I will add one group with a combo box and a button to the Home tab. I chose the Home tab, because choosing a style is among the 80% most used functions in Word (as you can tell from the MS-Styles group being on the Home tab). It won’t be pretty, but it will serve its purpose. Following is the RibbonX code for the example:

RibbonX code for StyleChooser add-in

Some of these things are already familiar to you, some are not. New are a bunch of callbacks and the comboBox tag. As I will discuss the callbacks later, let me point out a few attributes to you. You already know the “id”, “idMso”, “label” and “size” attributes. “insertAfterMso” does what its name implies, it inserts the group after the Font group on the Home tab. “screentip” specifies a simple tooltip. If you look at the tooltip for this group, you’ll see the screentip above the line and the supertip will be displayed below it. As I don’t define a supertip, it shows the name of the add-in. “maxLength” specifies the maximum length of a string that a user can input. I set it rather arbitrarily to 50.

About button

The about button is straightforward to implement and similar to the “Hello World” example I showed for VBA. The only difference is that I check this time in the code the id for the control and make sure it is equivalent to the id of the about button. I do this, because I personally prefer to write only one method for each ribbon callback signature and decide within the method on which control to apply it. The about button displays a simple message box. You have to include the Systems.Windows.Forms .NET reference to be able to do this though.

Populating the comboBox

The main goal of the add-in example is to let a user select a style from the list of all styles. The comboBox is supposed to show all styles when the drop down arrow is pressed and show in its field the currently active style.

Let me first insert the information for the currently active style. To do this, we need to use the “getText” callback. From the callback, we need to return the string that is to be displayed in the comboBox field itself. Note that the string has to match a string given to the drop down list, if you want the comboBox to correctly highlight the currently active style in the drop down list. As this is post is not about Word programming itself, please refer to the code to see the details of how the information is obtained from Word.

I also need to fill the entire drop down list with all available styles. To do this we need to implement two callbacks: “getItemCount” and “getItemLabel”. “getItemCount” tells Word how many items the drop down list will contain. “getItemLabel” is called for every single item to determine the string to display. “getItemLabel” will be called back as many times as “getItemCount” specified. Its signature contains an integer which is simply a reference to a zero based array. This means that the add-in itself needs to maintain internally the full drop-down list to display. As styles can be hidden, the example doesn’t reference directly the built-in Word Styles collection, but rather maintains its own styles list.

At this point, I need to introduce the IRibbonControl.Context property. This property is a handle to currently active window. Keep in mind that although Word has only one ribbon, many documents can be displayed at the same time. For each document, there is a different list of styles and a different currently active style. Therefore the add-in needs to account for it somehow. I chose to do that by using a Hashtable that has as key a Document object and as value an ArrayList of strings. When the “getItemCount” is executed, I build the Hashtable for that particular document and then return its count. For each “getItemLabel” callback, I simply access the Hashtable, then the ArrayList stored within and return the appropriately indexed element. Note that the “getItemCount” callback (and subsequently any “getItemLabel” callbacks) is only executed when the user clicks the drop-down arrow.

Reacting to a change in the comboBox

If the user selects a different style in the comboBox, that style should be applied to the current selection. In order to do this, I implemented the “onChange” callback for the comboBox. This callback passes the method the selected text, which can be passed on as is to the Selection.Style property of the Word object model (notice that I had to pass a reference to the object due to a PIA requirement).

Displaying the currently active style

The only problem the add-in has now is that it cannot react to any change in style in the document. For example, if the user moves the cursor to a paragraph that has a different style, this change is not reflected in the comboBox field. In order to be able to reflect the change, the add-in needs to implement the WindowSelectionChange event of the Application object. But what should the event trigger? This is finally where the last of the callbacks comes into play: “onLoad”. The “onLoad” callback is mainly there to give you access to the IRibbonUI object for your add-in. With that object, you can invalidate either all UI elements or just one particular one. Invalidation means that Office considers all values returned by the element’s callbacks to be invalid and also triggers a refresh of those callbacks. In other words, by invalidating a control you force Office to call its callbacks again, but of course only if the particular UI element is currently visible. To finish the add-in, I added the “onLoad” callback and included in that particular callback the statement to add a method to the WindowSelectionChange event. That method has one statement only, namely one to invalidate the comboBox control. If the Home tab is displayed when the event is triggered, Word will reload the text of the comboBox field and therefore display the correct style. You might notice a performance hit when you press the drop-down arrow of the comboBox. Recreating the ArrayList every time the drop-down arrow is pressed is unnecessary and this could be optimized.

Conclusion

I hope this COM add-in example illustrated a lot about RibbonX and COM Add-Ins in Office 2007. There is nothing in this example by the way that could not be implemented using documents or templates and VBA. If you don’t feel like implementing anything yourself, give the binary version of the add-in a try. You can add the comboBox to your QAT by right-clicking the drop-down arrow and choosing “Add to Quick Access Toolbar”.

Downloads

Revisions

  • V1.1 solves some of the setup issues, e.g. the add-in installing itself in weird program files folder (HCT).
  • I changed the location of the group to the right of the Styles group
  • Thanks to Bob Buckland for his helpful suggestions and comments!

Being A Good Citizen

June 9th, 2006 by Patrick Schmid

RibbonX lets you do a lot of things, but which ones are the right ones? How should your add-in behave and integrate itself into the Office UI? Where should you place your add-in? Which modifications are ok, which are not?

Today I am going to address all of these questions. In a more generic sense, I am going to talk about the User Interface Style Guidelines. As further reading on this topic, I suggest the Microsoft UI Style Guide. I should say though that this post goes beyond the style guide.

When you take RibbonX into your hands, the deciding factor on what you should do is whether you control (directly or indirectly) the Office application. You control the Office application, if

  • You are writing a full-fledged application based on it. The two most notable examples are Access applications and Excel dictator applications. In both situations, your code completely takes over the Office application frequently to the point where the user does not even recognize anymore that there is an underlying Office application.
  • You are dealing with your own Office.
  • You are designing the corporate “look” of an Office application. Many corporations choose to roll out Office applications with a set of add-ins and with a UI that is customized to the needs of the corporate users.
  • You are developing a template or document that is rather unique and offered in a corporate environment. A good example for a rather unique template is Word’s Blogging feature which displays a very different Ribbon. However, this template does not fit into the controlled category per se, because a user could install add-ins that modify the Blogging ribbon. If the Blogging template were to be used in a corporate environment with IT preventing the user from installing any add-ins him- or herself, then it would be controlled.
  • You are developing an add-in for a corporate environment. Generally, corporate IT controls which add-ins can be installed and hence you have some control about which other add-ins are changing the user interface.

You do not control the Office application, if

  • You don’t know and/or can’t influence what other add-ins, documents and/or templates might be installed in any Office application.
  • You are not developing for one particular client. That means, you are developing a commercial add-in that is available for anyone who wants to have it (via a free download, buying it, etc). If you are developing a customized solution for one particular client, you might be dealing with a controlled situation, but not necessarily.

The distinction between controlled and uncontrolled is crucial, because in an uncontrolled situation you don’t know (and have no way of finding out) what other add-ins, documents or templates might be doing to the User Interface. You also don’t have any way of figuring in changes to the basic User Interface by Microsoft (Office 14 might seem far away, but your program might be around a lot longer than 2-3 years on a machine. MS is skipping #13). In addition, you cannot control which locale (User Interface language) a user is running your add-in with. With Office 2007, changing the UI language is as simple as a few mouse-clicks. For example, I have the US English version of Beta 2 with the German language pack installed. While all Office applications are closed, I can change between US English and German in Start, All Programs, Microsoft Office, Microsoft Office Tools, Microsoft Office 2007 Language Settings.

If two add-ins (I am going to refer to templates, documents and add-ins that modify the Ribbon simply as add-ins. MS calls them “solutions” in their documentation) modify the same element on the Ribbon, the last one to load wins. As you cannot control nor predict whether your add-in will be the last one to load, this is an extremely indeterministic situation and one you should avoid at all cost. Therefore whether you are working in a controlled or uncontrolled situation, keep your UI modifications to a minimum. Let me know discuss the implications of both situations and then talk about modifying the Ribbon UI in general.

Controlled Situation

In a controlled situation, you could do whatever you wanted. I say could, because you should restrain yourself and follow the following guidelines:

  • Do not use RibbonX to restore an Office 2003-like UI. This might be tempting to avoid the training costs associated with upgrading, but it is not a forward looking investment. Future upgrades from Microsoft will probably require additional work. Most importantly though, you are not reaping any benefits from the new UI design. If you want an Office 2003-like UI, stick with Office 2003 and do not upgrade.
  • Follow the UI design principles I am going to outline later. You want to make sure that your UI is similar in behavior to the Office UI, so that users can transfer their knowledge of how to use Microsoft components to your own. Users might have no familiarity with the Office 2007 UI experience currently, but they will for sure have some one year from now and they will expect an identical behavior from your program.
  • Do not use the startFromScratch attribute for the ribbon tag unless you are developing an application based on an Office application. startFromScratch truly means that the ribbon starts from scratch. This is a killer approach when you have to deal with more than one add-in, even in a controlled scenario. Avoid it, avoid it, avoid it. If you have to use it, remember that you should ensure that only one, namely your, add-in contains RibbonX. If you use startFromScratch in a scenario with two or more add-ins modifying the ribbon UI, you are setting yourself up for a disaster.
  • Decide carefully about what you place in the QAT. There are only 40 spots and every one you use is one less your user has available. Users can place any ribbon control on the QAT and might want to make good use of this, even in a strictly controlled corporate environment. In contrast to previous Office versions, your users won’t be able to mess up most the User Interface and generate lots of support requests when they cannot find things anymore. You should leave them therefore some freedom to do with their QAT what they would like to do. Microsoft preloads the QAT with four controls (for some ribbons six). I suggest that you keep the number of preloaded QAT items to less than 15 (including the Microsoft ones). Note that you can only modify the QAT, if you are using startFromScratch.
  • “Everything starts from the Ribbon”. While Microsoft didn’t follow this mantra 100% of the time (there are commands that are not in the Ribbon, but can be added to the QAT. Some exist by default only in the QAT, namely Undo and Redo), you should try to follow it as best as you can. That means, do not put a control only in the QAT. All your controls should either be in the Office button menu or on the ribbon and only added to the QAT as an additional location to find it. That means, do not use the QAT as the primary and only location for a functionality. Remember that a user can remove any item on the QAT with a right-click followed by a left-click and if that was the only place where a user can access some functionality, then this functionality is now gone to the user and he or she probably needs support to get it back.

Uncontrolled situation

In this kind of situation, you really have to be a good Office citizen. The most important guidelines to follow are the following:

  • Do not use startFromScratch. Period.
  • Do not put anything in the QAT. The QAT is for the user to use, not for you to advertise your add-in. If the user wants to put any of your functionality in the QAT, he or she can do so manually. You however should never touch the QAT with RibbonX. Note that you only could modify the QAT if you are using startFromScratch, which you should never do in this situation.
  • Remember, your add-in is not the most important thing in the Office User Interface. Don’t make it prominently available just because.
  • “Everything starts from Ribbon” applies as well obviously.
  • Follow the general UI guidelines outlined below.
  • Make your add-in fit in with the rest of Office 2007.
  • Mark your add-in clearly as such in the UI. If your add-in blends seamlessly with Microsoft feature and there is no way to distinguish your add-in from any MS component, then your users will first go to Microsoft for help. Microsoft’s website already gets more traffic than your website, so why increase this even more? ;) To mark your add-in, include the words “add-in” somewhere where the user can see it. For example, include it as part of the Group label. Or add a labeled menu separator to the top of a menu like I did for my own add-in:

    Screenshot of RibbonCustomizer menu

  • Tell your users how to get in touch with you. For example, my add-in includes an About button that shows a dialog with my website on it.

Repurposing Commands

RibbonX lets you “hijack” any MS command and redirect it to your own add-in. As with any RibbonX conflicts, if two add-ins repurpose the same command, the last add-in to load wins. Except of a controlled situation, you should never repurpose a command. Even in a controlled situation, repurpose only when there is a very good reason (your own application based on an Office application is the only one that comes to my mind). Whenever you repurpose a command, the original functionality of the command is no longer accessible to the user or any other add-in at all. There is no workaround, the access to the Microsoft functionality is gone while your add-in is loaded (a bug in B2 seems to give access to the original MS functionality using shortcut keys). Repurposing is tempting, but here are two examples why you should not use it:

  • Word 2007 has built-in functionality for Citations & Bibliography. That functionality though is inferior compared to a full fledged citation manager like EndNote. EndNote comes with an add-in for Word to easily insert citations into documents. It would be tempting for EndNote to repurpose the Word 2007 controls for citations & bibliography on the References tab with a new version of the EndNote add-in to provide seamless integration into Word 2007. What happens though if the user gets a document that was created using the built-in feature? If EndNote repurposed all the built-in commands, the user won’t have any way of editing those citations, because access to the MS functionality would be gone. Repurposing becomes an even more problematic situation, if another citation manager, RefWorks, decides to do the same (ProCite and Reference Manager are two other well-known citation managers, but EndNote and those two are from the same company). If a user installs both, then the user might have one day access to EndNote via the built-in UI items and the other day to RefWorks, simply depending on which add-in managed to load first that day. A much better solution would be for EndNote and RefWorks to each add its own group to the References tab and leave the MS commands alone.
  • On the Mailings tab, Create group there is a control for Labels. As you might know, the label manufacturers provide add-ins for Word that are designed to work specifically with their labels. What if two label manufacturers, Avery and Herma e.g., decided both to repurpose that particular control to provide access to their custom label wizards? If a user installed both, which is quite plausible, he or she would have access to only one of the two wizards again depending on the load order of the add-ins. The user would also lose access to the MS label functionality.

Home Tab

If you want your add-in to be visible immediately when a user opens a Ribbon application, where do you put it? Of course on the Home tab. Are the commands of your add-in among the 80% most used commands when you count all MS and add-in commands? No? Does your add-in provide functionality that is similar to the functionality of the MS commands on the Home tab (or expands on it, e.g. a button to paste special as image)? No? If you answered no to both, then what is your add-in doing on the Home tab?

Do not put your add-in on the Home tab simply because you want users to be able to find it. Advertising your add-in is not a good reason to clutter the Home tab. Be a good Office citizen and remember that the Home tab is for the functionality that a users access 80% of the time.

Your own tab

It is tempting to create your own tab, but do you really need it or do you just want to advertise your add-in (as it would be prominently displayed in the tabs at all time)? The rule for creating your own tab is simple: If you can fill the tab, then make one, otherwise don’t. If your add-in can be categorized into any of the existing tabs, put it there except if you really need the space of a full tab. A full tab generally has at least 3 groups (a tab that is full but has only one group is a sign of a poor layout). Full means that when viewed with a 1024×768 resolution (the MS target resolution for the Ribbon UI), you cover at least 70% of the tab space (I made up that number, but that is my estimate how full the least full MS tabs are).

Your own group

Your own group is generally a good place to put your controls. The question is mainly where to put your group. If your functionality fits into any of the existing tabs logically, then put it there. Otherwise, use the Add-Ins tab. Remember that your functionality might fit logically best into a contextual tab, because it is only relevant when a picture, chart, table, etc is selected. If your add-in is limited in functionality to any of the built-in objects that have contextual tabs, then you should definitely place it there.

MS groups and controls

You cannot modify any MS groups directly. For example, if you wanted to add a paste special as image button next to the paste button in the clipboard group on the home tab, you’d have to make your own group and put it next to the clipboard group as you cannot modify the Microsoft group. What you could do is hide the MS group and create a new group that contains all the MS controls plus your own one. While this would conserve space, you should never do this in an uncontrolled situation. If you do this, you rob any other add-in from access to that particular group and you really don’t know what other add-ins might do. It is feasible that another add-in will display the Clipboard group again, if it loads after yours. In that case, the user would now suddenly have two Clipboard groups.

Avoid hiding or disabling MS controls and groups in a non-controlled situation. Again, you don’t know what other add-ins will do and what the overall effect for the user will be.

Use as little space as possible

Space is a premium on a tab. Microsoft groups will shrink in size and make space available for your groups (to see this effect, just make a window slowly narrower and watch what happens to the Ribbon). You cannot shrink your own groups automatically though. If your group uses a lot of space then that means that one or more MS groups shrink if the screen resolution is 1024×768, the screen resolution you should target in a non-controlled situation. As MS groups shrink though, the user has to click twice to get to the same functionality that he or she could get to with one click before your add-in was added. If your add-in uses space too freely and forces the user to click too much, the user might just get annoyed with your add-in and your add-in will get uninstalled. Remember that space is at a premium and it is your job to use it wisely. Also remember that yours might not be the only add-in on any particular tab using space. You should consider using a menuButton, splitButton or a dynamicMenu for all your functionality to use as little space as possible.

Add your functionality only once

There really is no need to put your functionality in more than one place, except if you are working with some contextual tabs. For example, the Format contextual tab is repeated almost identically for SmartArt graphics, charts and shapes. If your add-in extends the functionality offered on that tab, then you should add it to all relevant tabs.

However, there is no reason to put your functionality on two regular tabs. Put it only in one.

Visibility

You can change the visibility of tabs, groups and controls dynamically. Don’t. If you go through the Office UI, you should notice that no group, tab or control ever disappears or appears magically. If something is not available, it is visible but not enabled. The rule is: From the time you open a particular ribbon to the time you close it, the visibility of your items should not change (exceptions below). Don’t change the visibility of your controls ever during runtime. You should determine the visibility once and then leave it at that. As an example, the Ink group on the Review tab is only visible if you have a Tablet PC, but this visibility is never altered during runtime. Office determines at startup whether you have a Tablet or not and sets the visibility accordingly.

In Outlook, the same ribbon should always look the same as well. Keep in mind that Outlook asks you once to specify a particular ribbon and even though the user can close the window with that ribbon, Outlook never asks you again. Why should you not change the visibility? The Ribbon UI is all about the user finding features. If your UI elements are visible, but not enabled, then the user knows that the functionality is there, but that he or she cannot use it currently. If your UI elements are not visible, the user will go searching for them and become frustrated. Your user will even be more frustrated if one time they are suddenly there and another time they aren’t. Remember that whether something is visible or not might be logical to you (as it is context dependant and you know what the context is), but to your user this might be totally random and only a source of frustration.

There are exceptions to the rule of course. It could be that a certain user action triggers a fundamental change. For example, you might require the user to log in somewhere and after a successful login, a lot more functionality is available to the user. This is a stretch and a situation you should try to avoid, but it would be a case where you might be able to get away with changing the visibility during runtime. Creating your own custom contextual tab is an example too. I will show you in a later post how to do that.

Changing UI elements dynamically

You might want to change UI elements dynamically in a rather drastic manner. Again, don’t. Look at the Office UI itself and you will see that no group (including all controls, labels and icons) ever changes during runtime. The reason is the same as with the Visibility issue.

If you have to change your UI dynamically, do what Office does: Change a menu. You might notice that the menus that you can open from Ribbon buttons change their content frequently yet the buttons themselves stay. You can do the same by using a dynamicMenu.

To sum up: Leave your groups and controls visible and unchanged during runtime. Use a dynamicMenu to deal with dynamic UI modifications.

Office button menu

Again, the Office button menu is no place to simply advertise your add-in. Add commands to it if your add-in affects the entire document. As you can see from the built-in menu, sharing, printing, sending, saving, opening are there instead of in the ribbon.

Custom Task Panes

According to the Office UI style guide, you should use a Custom Task Pane, if “your solution needs to present data about a document that is required to be visible, in a non-modal fashion, use a custom task pane. However, only display this task pane based on user actions. Also use if you need to use custom controls that are outside of the Ribbon control set.”

No surprises

The Office UI style guide summarizes this one best: “Task panes or dialogs do not appear automatically on document open. Only user actions should open and close task panes or dialogs. Ideally, all task panes are opened using a button in the Ribbon. For example, clicking the launcher button on the Clipboard group open and closes the Clipboard task pane. ”

Switching a tab

I showed you in an earlier post how to switch a tab into the foreground. What I didn’t talk about was when you should do that. Almost never is the answer. You should only trigger a tab switch when you are dealing with your own custom contextual tab (again, how to do that in a later post) or when you had to reload your add-in and need to get back to the tab the user was on when you triggered the reload (when you reload your add-in, Office switches back to the Home tab). I’ll save the reason for why you’d want to reload your add-in for later as well.

First tab

What I didn’t mention yet is that Office doesn’t necessarily treat the MS Home tab as the Home tab (the one it shows at startup and returns to by default). Rather, the first tab is treated as such. That means you could create your own tab, put it in order before the Home tab using insertBeforeIdMso=”Home”. The answer to when you should do this should be rather clear by now: Never, except in a controlled situation and even then very sparingly (think, your application based on an Office application).

I can’t think of anything else right now. If more comes up later, I will edit this post.

Edits

  • Edited to include the information that the QAT can only be altered via RibbonX, if startFromScratch (=”true”) is used. (June 18, 2006)

Developer: “Hello World” in Excel, PowerPoint and Word with VBA (Part 3)

June 5th, 2006 by Patrick Schmid

My last two posts explained how to modify the Office UI using RibbonX embedded in a document or template. Today, I am going to discuss how to react to an event from a UI element in VBA. As example, I will display a message box with the word “Hello World” when the user clicks the “Hello World” button created in the first two parts of this topic.

Before I can get started on this though, I need to talk a little bit about Macro Security. In Office 2007, documents and templates that contain macros are trusted automatically if they are stored in a Trusted Location. To alter your Trusted Locations, go into Office Button, Options, Trust Center, Trust Center Settings, Trusted Locations. There are two observations noteworthy here: First, you “My Documents” folder is not trusted automatically, nor are any of its subfolders. Secondly, by default, you cannot add a network location as a trusted location unless you specifically enable this in this dialog. If you don’t want to alter your Trusted Locations, you can always press “Enable Content” after you loaded a document or template with a macro into Office (you have to do this every time you open the file). Explore the rest of the Trust Center and see what other options you have for security and privacy settings there when you have some time.

If you remember my overview post, the third step was the actual add-in being used via callbacks. Today, I am going to discuss how to specify a callback for a button in RibbonX and how to implement the callback in VBA.

Let me start out by showing the function in VBA that the button “Hello World” will trigger:

Sub onHelloWorld(control As IRibbonControl)

    MsgBox (”Hello World”)

End Sub

The only noteworthy thing about this function is its argument control. This argument lets you know the UI element that triggered this particular callback. With control.Id e.g. you can figure out the id of it. You have to include this argument, otherwise the signature of the function is incorrect and it will not be called.

To tell Office to call “onHelloWorld” when the “Hello World” button is pressed, modify the RibbonX file with the Office 2007 Custom UI Editor:

RibbonX code modified with onAction callback

The modification I made was to insert onAction=”onHelloWorld” as an attribute of our button. The attribute “onAction” was defined by Microsoft and specifies the callback for when the button is clicked. Please notice that I only specified the function name and not its full signature in the attribute. Office knows what the signature of the function has to be and therefore it is sufficient to only specify the function name.

Once you modified the file and open it in Word, you should be looking at the dialog box, when you press the button:

screenshot of message box

You can also download the sample.

I will take a break from my Hello World series with my next post and instead focus on how to best integrate your add-in into the new UI from a conceptual/style point of view.

Developer: “Hello World” in Excel, PowerPoint and Word with VBA (Part 2)

June 3rd, 2006 by Patrick Schmid

Yesterday, I discussed how you can write some sample RibbonX code and insert it into a document or template. Today, I am going to talk about a tool that takes care of the insertion step for you. The tool is called the “Office 2007 Custom UI Editor” and is a free tool from Microsoft. You can download it from openxmldeveloper.org. The tool requires the .NET 2.0 Framework.

Once you have installed it, open it and take a look:

Office 2007 Custom UI Editor

The tool has the following features:

  • XML editor with color coding
  • RibbonX Schema Validation
  • Four RibbonX Samples
  • Insert RibbonX code into any Office 2007 document or template
  • Edit any RibbonX code contained in an Office 2007 document or template
  • Insertion of icons (I will skip this feature until a later post)

You saw the XML color coding already in the screenshots of XML code in my previous post. The feature colors tags, attributes and values differently. The RibbonX Schema Validation is an XML Schema Validation that validates a RibbonX file against the RibbonX XML Schema. That means, it checks whether the RibbonX code is syntactically correct RibbonX code. It only checks the form of your RibbonX code, but not the content. That means you can write RibbonX code that validates, but still fails when loaded into Office, e.g. because you specified an incorrect idMso or used the same id twice.

It ships with four RibbonX samples: Custom Tab, Excel - A Custom Tab, Repurpose, Word - Group on Insert Tab. Those examples show you the RibbonX code for these tasks and help you getting started with RibbonX.

The most useful feature of the tool is its ability to insert your RibbonX code into any Office 2007 document or template. To see how this works, use File open to open the helloWorld.docm you created if you followed yesterday’s post. You’ll see the following screen:

helloWorld.docm in Office 2007 Custom UI Editor

Notice that it correctly found the XML code in the docm file and displayed it to you. Edit the XML and replace the label of the button with “World Hello”. Save the file and open it in Word. As expected, the button now reads “World Hello” as label.

To work with a document that does not yet have RibbonX code embedded, create the document or template in Excel, PowerPoint or Word first, then open it with the Office 2007 Custom UI Editor. Now you can add your RibbonX code and save it in the file. Voilá, the file will now load your customized Ribbon when you open the file in the respective Office application.

If you are curious and want to know what the tool actually saves in a new file, here is the short summary: The tool creates a new folder called “customUI” in the top level of the zip container. It stores the RibbonX code in a file named “customUI.xml” in that folder. Then it adds a line to the “.rels” file in the “_rels” folder. The difference to what you added yesterday there yourself is that the target filename is preceded by a “/” (in contrast to the other entries created by Office, but identical in meaning). The Id it generates for the relationship is random in nature.

I would highly recommend to use this tool, as it greatly simplifies the process of adding and changing RibbonX code in documents and templates. I will post the third part probably on Monday.

Developer: “Hello World” in Excel, PowerPoint and Word with VBA (Part 1)

June 2nd, 2006 by Patrick Schmid

Sorry that the post is late. It took me a lot longer to write this than I thought it would. The post today is going to show you how to do the following in Excel, PowerPoint and Word from a document or template:

Screenshot: Hello World button on Home tab

Specifically, I will show the following:

  • How to add RibbonX to a document or template
  • How to add a group with a label to the Home tab using RibbonX
  • How to add a button to this group with a label and icon using RibbonX

In the second part, I am going to show you the free tool Microsoft offers to make your life a lot easier when writing RibbonX for documents and templates. If you know of any other tools that are already out there, please post a comment and I will make sure to include it in my discussion. Part 3 of this will show you how to implement an action in VBA that is triggered when the user presses the “Hello World” button.

Writing RibbonX code

If you remember my overview from the last post, the first step in customizing the Office UI is the RibbonX code itself. For this sample, I am going to use the following code, which works for Excel, PowerPoint and Word:

Hello World RibbonX code
The first line specifies that this is a UI modification for Office 2007 and points to the XML Schema that defines what the syntax of RibbonX has to be (RibbonX XML Schema, sorry that it is not a link to MSDN. I couldn’t find it there, but it should be there) .

The ribbon tag specified that this is a modification of the ribbon. If you have read about RibbonX already, you will know that you can also modify the QAT and repurpose Office commands (having your action triggered when someone uses an MS control) with it. You might have seen in other examples the attribute startFromScratch=”false” used with the ribbon tag. Specifying it as false is not required, because that is the default. Specifying true means that you want to start with a blank ribbon and only have the items on the ribbon specified in your RibbonX code. That setting is only recommended if you truly have a completely different ribbon for your application (the most common use of this is probably with Access applications and Excel Dictator Applications). If you modify the Ribbon only slightly, do not use startFromScratch=”true”.

The following tag (tabs) specified that we are dealing with the main tabs and not contextual tabs. The tag (tab) indicates the actual tab we are working with. The attribute idMso means that we are using an MS-provided tab, in this case the Home tab. If I had specified an attribute id instead, I would have been creating my own tab.

With the next line, I am adding a group to the Home tab. This group has the id “helloWorldGroup” and I gave it the label “Hello World”. Note that labels are optionals, ids (or idMsos or idQs) are not.

The following line adds a button to the group. The button will be large (size attribute), have the id “helloWorldButton”, the label “Hello World” and use the icon the MS-control with the id “Conference” has. If I had written “Paste” instead, I would have been using the image from the MS-Control Paste. To figure out the idMso of all MS controls, either download the control ID list or go into Options, Customization. In that dialog, the tooltip in the list of controls you can add to the QAT will show you the idMso in parenthesis:

Tooltips containing idMso

The remaining lines are the closing tags XML requires (in XML, all tags that were opened need to be closed again in reverse order of opening). Notice that the tag <button … /> is an XML shorthand for <button …></button>. You can use this shorthand if a tag does not contain any other tags.

You can copy & paste this code into Notepad e.g. and then save the file as “customUI.xml” on your Desktop. You can also download the file.

Loading RibbonX code into Word via a document

Now that you have your RibbonX code written, you need to load this into Office. For the first example, I am going to use Word and load the code via a document.

Before you get started with any RibbonX loading, you should activate the display of RibbonX errors: In Word, you can find the settings in Word Options, Advanced, General, “Show add-in user interface errors” (at the very bottom of that long list of settings). It’s called the same and in the same spot for all other Ribbon apps. If you enable it in one program, it will be enabled for all. You absolutely should enable it, because if you don’t, Office will not tell you when you made a mistake in your RibbonX code and you will be wondering why certain things are not displayed or don’t work.

You can only load RibbonX code from a document or template in the new XML-based Office 2007 file formats. If you don’t know anything at all about them, you can find a lot of background information on Brian Jones’s blog. I will explain though the basics you need to make your RibbonX code work.

The new file formats are nothing else than a collection of several files, mostly in XML format, zipped together. I say mostly, because media files (pictures etc) are stored in their original form in the zip container as well. All these files are woven together using the Open Container Format. The short explanation for what that is, is that even though all files are present in the zip container, all files need to be referenced in a tree-like structure. There is one central XML file that contains relationships to the top level XML components. Those in turn have relationship files that link in to the next level components, etc.

To add your RibbonX code to a Word document, all you need to know is that you need to modify the top-level relationship XML file and a relation there to your customUI.xml file. If you just add the customUI.xml file to the zip container without adding that relation, Office will give you an error. Due to a bug, that error might claim that Office has trouble accessing the file itself instead of telling you that the problem is within the file.

To get started, you need a Word document to work with. Open Word, and when you have the default blank file in front of you, click the Office button, Save As (yes, this is a button you can click). As type, choose Word Macro-Enabled Document (*.docm) and save the file on your desktop as helloWord.docm.

Close Word and rename the file into helloWord.zip (if you don’t have extensions displayed by default, open any folder in Windows Explorer, go into Tools, Folder Options and deselect in the View tab “Hide extensions for known file types”). To rename the file, right-click it and select Rename, then replace .docm with .zip. Windows is going to ask you whether you really want to do this, say Yes. If you now click on the file, it will open with your default zip program. If you don’t have a program like WinZip installed, it will open with the Windows built-in zip folder functionality. I am going to use that one in my example (if you have another default zip program, right-click the file, select Open With and select “Compressed (zipped) folder”). You should see the following window then:

opened Zip file

As the first step, you are going to add your XML file to this zip container. We could add the file wherever we wanted, but for this example, let’s add the file to the “word” folder. Click on “word”. Then copy the file customUI.xml from your desktop (right-click, copy) and paste it into this folder (right-click, paste). After that, go back to the top-level folder of the zip file shown in the screenshot above and click on “_rels”. The file “.rels” is the top-level relationship file that we need to edit. Right-click it, say copy and paste it onto your Desktop. Then open it with notepad (open Notepad from All Programs, Accessories, select File, Open, change file type to all files and select the “.rels” file). You will probably see something like this:

If you only see two lines of text, activate Format, Word Wrap.

You should notice that this is not a neatly indented XML file like the RibbonX code I showed above. The reason for that is that XML doesn’t care about whitespace (tabs, enter, spaces). In fact, whitespace reduces the performance when reading an XML file which is why all XML of the new Open XML format avoids whitespace. If you like to see your XML neatly aligned, you should get an XML editor that is able to “pretty print XML”. One such editor is Altova XMLSpy. You can get the Home version for free. The pretty-print feature is in the Edit menu.

I used it to get this pretty-printed version of the .rels file:

.rels file
What we want to do is add a relationship to this file. A relationship needs an Id, which has to be unique. It doesn’t matter though what you pick as Id, as Office will reassign them every time it saves a file anyhow. The important thing is to get Type correct. Type has to be: “Type=”http://schemas.microsoft.com/office/2006/relationships/ui/extensibility”. As Target, you need to set the path to the customUI.xml file. In this case, we specify “word/customUI.xml”. I should note at this point that the filename doesn’t matter either. Word will identify the file using this relationship tag only. The finished Relationship tag looks like this:

<Relationship Id=”customUI” Type=”http://schemas.microsoft.com/office/2006/relationships/ui/extensibility” Target=”word/customUI.xml” />

And the entire .rels file now like this:

.rels file
You can now save the file, copy it from the desktop and paste it back into the “_rels” folder of the zip folder (making sure to overwrite the .rels file there). After that is done, close the zip folder and rename the file back into “helloWorld.docm”. You can download the file as well. You can now open your file in Word and should see the following:

hello World button

It could be the case that Word presents you with an error message when you open the file. If the error message dialog has as its title “Error Loading Custom UI XML” (see the screenshot below for an example), then the error is in your RibbonX code.

RibbonX error message

If you see a different error message, e.g. the following, the error is in the “.rels” file.

.rels file error message

What could you have done possibly wrong? A good guess is that XML is CASE-SENSITIVE, which means if you don’t follow the exact capitalization, you will get that error message. Please remember the following: “Id” has a capital I in the “.rels” file, but “id” is all lower case in RibbonX! (I made that mistake myself first while writing this). Another thing you might want to look at is quotes (”). When a blog post is published from Word, it can very well happen that you end up with curly type quotes instead of the straight ones. You have to make sure that your quotes are the standard straight ones.
Off-topic: Did I mention that blogging in OneNote has one great advantage? When lightning causes a power spike that switches off your desktop while typing, you don’t lose much. In my case, I think I lost 3 characters in total!

Loading RibbonX into Excel, PowerPoint and Word documents and templates

The procedure for loading RibbonX into other file types is exactly the same.

For Word documents use “Word Macro-Enabled Document (*.docm)”

For Word templates use “Word Macro-Enabled Template (*.dotm)”

For Excel documents use “Excel Macro-Enabled Workbook (*.xlsm)”

For Excel templates, use “Excel Macro-Enabled Template (*.xltm)”

For PowerPoint documents, use “PowerPoint Macro-Enabled Presentation (*.pptm)”

For PowerPoint templates, use “PowerPoint Macro-Enabled Template (*.potm)”

The next post will showcase a free tool from Microsoft that inserts RibbonX code for you into Office documents.

Edited to fix the pictures and include the quote remark. Thanks Greg for pointing both things out!

« Previous PageNext Page »