As part of my job, I debug and mitigate application compatibility issues with Windows Vista for customers who are migrating to the operating system. Along the way, I also get my fair share of Office 2007 questions (on which I am no expert) since these two products are, more often then not, being deployed together. (We call this DOVO - Desktop Optimization with Vista and Office. We like acronyms here at Microsoft.)
I came across an interesting issue today. My customer had an application which, for Office 2003, had created a new toolbar, and then used VBA to disable every other toolbar on the system (using the CommandBars object). They were calling out each CommandBar by name, so the process was inherently somewhat fragile. And, sure enough, on Office 2007, some things weren't disabled.
Now, there were a couple of different approaches we could take. One would be to just find out which CommandBar objects were left out, and snag them as well. The other is to just disable everything and only enable what you specifically want.
Then, on one of our internal discussion lists, somebody (who clearly knows Office better than I do) suggested just customizing the ribbon.
You know, because what is the value of having 9 tabs sitting up there when eight of them contain only controls that are grayed out? (And also because having everything crammed together on the Add-Ins tab with their tiny little icons looks like ... erm ... looks not so great.)
So, my next question was - how hard is that to set up?
And boy, I can't believe how easy it is.
First, I created a new docm document. I saved it to the desktop, and renamed it document.docm.zip. So, now I can open it like a Zip file.
I then created a new folder on my desktop called customUI, and created an XML document inside of it called customUI.xml. I grabbed the schema for the customUI XML from here: http://www.microsoft.com/downloads/details.aspx?FamilyId=15805380-F2C0-4B80-9AD1-2CB0C300AEF9&displaylang=en. I installed the xsd into the Visual Studio 2008 schema cache, and cooked up a quick and dirty XML file:
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" > <ribbon startFromScratch="true"> <tabs> <tab id="WorkInstruction" label="Work Instruction"> <group id="SampleGroup1" label="Sample Group"> <button id="Button" imageMso="HappyFace" label="Insert Company Name" size="large" onAction="ThisDocument.InsertCompanyName" /> </group> </tab> </tabs> </ribbon></customUI>
The startFromScratch attribute in the ribbon object is the key to clearing out everything that's there, so only the things you specifically add show up (which is a far better user experience than seeing all of the controls but having none of them work, in my opinion).
I then dragged that customUI folder into the zip file (really my docm file).
Then, I browsed to the rels folder, and edited the .rels xml file to add a relationship for the customUI so it became the following:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"> <Relationship Id="rId3" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/> <Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail" Target="docProps/thumbnail.wmf"/> <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/> <Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/> <Relationship Id="someID" Type="http://schemas.microsoft.com/office/2006/relationships/ui/extensibility" Target="customUI/customUI.xml" /></Relationships>
I then inserted this back into the zip file, and renamed it back to a docm file.
I had to add a bit of code to handle the button click, so I just took one of the samples and used its code:
Sub InsertCompanyName(ByVal control As IRibbonControl) Dim MyText As String Dim MyRange As Object Set MyRange = ActiveDocument.Range MyText = "Microsoft Corporation" MyRange.InsertBefore (MyText)End Sub
And that was it. Less than half an hour, and I had a totally customized ribbon that used the more foolproof method of starting from scratch and then adding stuff than the method of starting with everything and disabling things by name until I had gotten rid of everything that I can think of.
Seriously, it was so cool to see this with such a minimal investment of time. Half an hour, tops. Makes me wonder why our own internal Office tools are still sitting in the add-ins tab...