Viewing and editing Sharepoint properties on a Word document… again

I have posted before about a method of editing the SharePoint Document properties on a Word document in Office 2010 (and Office 2007). I just found something that completely blew my mind. I spent hours and hours battling with CustomXMLParts, Protected and Readonly documents, and a Save-As dialog… and found out that all that effort was pretty much wasted.

Behold:
_Document.ContentTypeProperties Property
Microsoft.Office.Interop.Word.Document.ContentTypeProperties

ContentTypeProperties is a collection of MetaProperty objects representing (possibly among other things) the SharePoint properties displayed in the server document properties panel. And you can edit them.

So instead of a mess of XML xpath, namespaces, exception handling and “_x0020_”‘s , if you want to edit a sharepoint list column called “Task Id”, you would do the following:

doc.ContentTypeProperties["Task Id"].Value = "task1";

(Yes, you still might need some exception handling…)

The CustomXMLParts will be updated appropriately, and when you save it to sharepoint, the properties will be populated.

Have a look at the members of the MetaProperty object:
.Name = sharepoint internal column name: “Task Id”
.Id = escaped column name: “Task_x0020_Id”
The other properties are what you would expect.

Please note that this will only work if the word document has been “touched” by SharePoint. See my next post for a quick (and undocumented) method of getting those properties attached in Word 2010.

Embedding vzaar video in SharePoint 2010 page

vzaar.com is a video hosting service (kind of like Brightcove, only cheaper) that can be used to stream and manage video content when you don’t want to, or cannot serve it up yourself. You could use youtube, but, well, do you really want to embed youtube in your corporate extranet?

In my case, we wanted to video embedded into a SharePoint 2010 page.

Turns out, sharepoint strips out the embed code pasted into the HTML editor for a page. After much searching (see previous post) I came across a method of embedding flash videos, that is made even easier for vzaar videos by the API.

1. Add a Content Editor web part to your page.
If the page is web part page, this is as simple as clicking any “Add Web Part” link in the page editor.
If it is a “wiki-style” page, you will need to go to the Insert ribbon tab, and select Web Part

2. Select the “Media and Content” category, then the “Content Editor” web part and click Add.

3. Open the Content Editor Web Part properties, paste the “basic embed code (api call)” from the vzaar video, click OK
(To get the basic embed code, in your vzaar video library click the Manage link next to the desired video, and scroll to the bottom)
(To open the content editor properties, either click the dropdown in the web part, or click on the web part and use the Ribbon tab)

That’s it. Your video should now show up embedded right in the sharepoint page.

Embedding flash video in SharePoint 2010 page

The SharePoint 2010 page editor allows you to edit the raw HTML for a page with one huge caveat: it strips out anything it considers unsafe. Including object tags you might use to embed a flash video.

There are quite a few articles / forum posts online with workarounds that either don’t work, or are far too complicated for the average power user.

Then I found this blog post:
Adding Flash Content to SharePoint 2010 / Office 365

While I don’t usually post about things other have already figured out, for some reason Bert’s article took me quite a while to find.

I will be posting a simplified version of his steps for use with the vzaar video hosting service soon.

Stainless steel forks and aluminum foil…

Ever since I can remember, I have had a peculiar sensitivity — when a fork (or piece of stainless steel cutlery in general) has recently come into contact with aluminum, I find the fork to have a most unpleasant taste.

Since it is my goal with this blog to answer (or at least bring to light) the questions Google fails, I can find no information on the phenomena. Perhaps a kind reader will have some clue as to what is going on, and if there is any more info anywhere.

When the fork has touched aluminum – such as serving from an aluminum pie plate or aluminum foil lined pan – something happens to the fork whereby upon touching it to my tongue I experience a funny “taste” or strange sensation. (Personally, I find the sensation unpleasant enough as to need a new fork.)

I would liken the taste to a mild form of the feeling one gets from testing a AA battery with one’s tongue.

It makes sense that when steel touches aluminum a current is induced at the juncture – dissimilar metals and all. But what exactly am I detecting? Is it electrical activity from the few aluminum ions on the end of the fork?
And why does washing it make it go away?

Most importantly, are there other people who have experienced this? If so, why is it so hard to find a reference or mention? If not, what is so special about my tongue 😛

Office 2010 Backstage OnShow callback contextObject

The signature for the Office 2010 backstage OnShow callback looks like so:

void Backstage_OnShow(object contextObject)

But I cannot find anywhere that documents what the contextObject is.

Well I can tell you – it’s the Window object that is hosting the backstage as shown. I’m guessing it’s an object because it will be the equivalent Window object in whichever Office application happens to be running.

Undocumented Office Ribbon Callback functionality

I just stumbled on an undocumented feature of the getImage callback for the Office 2010 Ribbon (well, backstage actually)

The “official” callback signature is

Public System.Drawing.Bitmap GetImage(Office.IRibbonControl control) {}

Or sometimes

Public stdole.IPictureDisp GetImage(Office.IRibbonControl control) {}

I don’t know which is “best”, but if you return a Bitmap it sure is easier to work with.

Now back in Office 2007 there are a couple controls with a GetImageMso callback that allows you to provide an Office Control ID for a built-in image. This is lacking from any 2010 backstage controls.

Whilst doing some unpleasant native debugging to try to “figure out” what office expects in these callback delegates, I tried creating a GetImage callback that returned a string.

<?xml version="1.0" encoding="utf-8"?>
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="Ribbon_Load">
  <backstage>
    <tab id="MyTabShare" label="Testing">
      <firstColumn>
        <group id="MyGroup">
          <topItems>
            <imageControl id="imageControl1" getImage="GetImage"/>
          </topItems>
        </group>
      </firstColumn>
    </tab>
  </backstage>
</customUI>
        public string GetImage(Office.IRibbonControl control)
        {
            return "hello world";
        }

I was really hoping for an error about a bad callback signature, possible including an exception in MSO.DLL that I could dig into…

Instead, I got this:

Really… So when GetImage returns a string, Office interprets it as an ImageMso? I had to try:

        public string GetImage(Office.IRibbonControl control)
        {
            return "WindowKeepOnTop";
        }

The result: SUCCESS!

So, at least for the Office 2010 backstage ribbon, the getImage callback has an alternate signature:

string GetImage(IRibbonControl control)

Where string is an Office Image Id (or the value you would place statically in imageMso).

Definitive complete list of Office Ribbon Callback Signatures for 2007 and 2010

Microsoft’s documentation for programming the Office Ribbon is pretty sparse at best. There are two pages you can get Callback signatures:
1. Customizing the 2007 Office Fluent Ribbon for Developers (Part 3 of 3)
2. Introduction to the Office 2010 Backstage View for Developers

Notice that neither of these documents sound like where you would expect callback signatures “part 3 of 3”, and “introduction to the…” Also, the backstage introduction article contains rehashes of most of the office 2007 callbacks in a painfully verbose fashion.

I am here to help.
How about an excel spreadsheet containing the callbacks, associated control, source (2007 vs 2010) and the signatures in 4 different languages? Did I mention the data is already in a table and sorted by callback name?

Here you go:
Full Office Ribbon Callback List
Update: I have uploaded this file to a public SkyDrive so it can be viewed online, since I have needed to make some changes:
Office Ribbon Callbacks

This document is not a control -> callback mapping. The typical use case is:
I am building Office customizations using xml.
I need to implement X callback, but do not know the signature.
I look up the callback by name, then make sure it is the correct one for my control.

Also, I didn’t quite finish reconciling some discrepencies between the 2010 and 2007 documentation – for example, in 2007 the getImage is supposed to return an IPictureDisp – which is a real pain in the butt. My experience showed that returning a bitmap worked anyway, and now the 2010 documentation says getImage returns System.Drawing.Bitmap. I have switched to using Bitmap because it is so much cleaner, but I figured I should leave them both in there.

I am open to suggestions – just trying to fill what I consider a documentation gap.

Pre Populate SharePoint Document Properties in a Word Document

The integration between SharePoint and Microsoft office contiunes to improve with every successive release, but as of Office 2010 and SharePoint 2010, there is still a bit of feature gap when it comes to automation.

When a document originates from within SharePoint it is not too bad – you have to do a little CustomXMLPart trickery to set the properties. But what if your file is a SharePoint virgin?

The adding a document to sharepoint adds at least 3 additional Custom Xml Parts to the Word Document – one of them big, complex and guid-filled. To generate these parts would be a bit of a nightmare.

Turns out, you don’t need all of the xml to pre-populate fields. Nor do you need any guids. Here is all the XML you need:

<?xml version="1.0"?>
<p:properties xmlns:p="http://schemas.microsoft.com/office/2006/metadata/properties" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:pc="http://schemas.microsoft.com/office/infopath/2007/PartnerControls">
  <documentManagement>
    <SharePoint_x0020_ColumnName>Text Value</SharePoint_x0020_ColumnName>
  </documentManagement>
</p:properties>

I will leave it to you to figure out the column names (hint – spaces become “_x0020_”).

Store that xml bit in a string (say, xmlString), and call Document.CustomXMLParts.Add(xmlString);
Now, when the document is saved to sharepoint, the fields will be pre-populated, all the appropriate xsd and guids updated, and the user gets no errors about missing required fields!

Changing the value of an editBox office Ribbon Control at runtime

When creating VSTO Add-Ins that customize the Office Ribbon, the visual Ribbon editor makes some tasks trivial. All Ribbbon controls can be accessed by id using intellisense. The RibbonEditBox.Text field can be directly queried and modified.
Everything changes when you create the RibbonXML directly.

You cannot directly query any of the runtime values on a ribbon control. You must use the OnChange callback to get the value in the box.

        public void OnChange(Office.IRibbonControl control, string text)
        {
        }

But what if you wanted to change the value of the editBox (aka change the text)? Say perform some validation, or formatting?

I tried casting the IRibbonControl object supplied by the callback to a RibbonEditBox object… This didn’t work.
I tried casting the control object as a Dynamic and accessing the “Text” property… No dice.
I looked for some means of getting the ribbon control so I could modify the Text value – nothing.

The solution:
(Which was surprisingly difficult to find)
There are three things you will need to do:
1. Within your ribbon’s class, make sure you are saving the IRibbonUI reference provided by Ribbon_Load to a private variable. I just call it “ribbon”
2. Implement the getText callback and a private string variable to hold the internal value for the editBox
3. Implement the onChange callback to perform validation, update the private variable, and use the IRibbonUI object to invalidate the editBox control. This triggers the ribbon to call the getText callback again, effectively updating the field.

An example:
This snippet when merged into the Ribbon class, will ensure that the text entered in an edit box ends with “of doom”

First, the ribbonxml part

<?xml version="1.0" encoding="UTF-8"?>
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="Ribbon_Load">
  <ribbon>
    <tabs>
      <tab id="DoomedObjects" label="DoomedObjects">
        <group id="spg" label="Stuff">
          <editBox id="txtDoomed" label="Doomed" onChange="OnChange" getText="GetText"/>
        </group>
      </tab>
    </tabs>
  </ribbon>
</customUI>

And the c# for the Ribbon class

        private string textValue;
        private Microsoft.Office.Core.IRibbonUI ribbon;


        public void Ribbon_Load(Office.IRibbonUI ribbonUI)
        {
            this.ribbon = ribbonUI;
            textValue= "";
        }

        public void OnChange(Office.IRibbonControl control, string text)
        {
            if (!text.EndsWith("of doom"))
            {
                textValue = text + " of doom";
                ribbon.InvalidateControl(control.Id);
                //Only invalidating when the value needs to change. You could invalidate after the if block as well 
            }
            else
            {
                textValue = text;
            }
        }

        public string GetText(Office.IRibbonControl control)
        {
            return textValue;
        }


Behaviour of Application.MailMergeAfterRecordMerge Event

The signature for the Application.MailMergeAfterRecordMerge event looks like this:

        void Application_MailMergeAfterRecordMerge(Word.Document Doc)
        {
        }

While I would have expected the Document referenced in the Doc parameter to be the newly created merged document, it is actually a reference to the document from which the merge occurred. In other words, it’s not really all that useful.