Feb 17
Word 2010 Retrieve and Set Properties
Posted by Wei in C#, SharePoint, VSTO on 02 17th, 2011| | No Comments »

There are 3 types of properties for Word Documents... that's right, 3. Not 2. Initially I thought there are the Built in properties and the custom properties. But then, there are also content type properties.

I'm not sure how to explain this, but I'll do my best. Content Type properties are set in SharePoint. A custom content type is created and this custom content type inherits columns which are also set in SharePoint. I won't go into detail about how that is set up but it requires you to Allow Management of Content Types for the document library.

Once that is done and the columns added for this content type, they will appear as Content Type properties in the Word document. This means that when the user opens the word document, they can see the custom content types available for them to fill in.

Whatever the user enters into these custom content type properties will be saved into the columns of the list when the user saves the document. Note that if the user saves the document as a PDF, the columns will not be populated with the properties.

Anyway, to go back on to my topic of how to retrieve all 3 types of properties, here is the code:

Microsoft.Office.Interop.Word.Document currentDocument = Globals.ThisAddIn.Application.ActiveDocument;

DocumentProperties builtInDocProperties = (DocumentProperties)currentDocument.BuiltInDocumentProperties;
DocumentProperties customDocProperties = (DocumentProperties)currentDocument.CustomDocumentProperties;
MetaProperties contentTypeProperties = (MetaProperties)currentDocument.ContentTypeProperties;

// for each of these properties, I placed them in a Hashtable for ease of querying later
Hashtable htProperties = new Hashtable();

try
{
    foreach (MetaProperty prop in contentTypeProperties)
    {
        try
        {
            htProperties.Add(prop.Name, prop.Value);
        }
        catch { } // some property names/values cause exceptions, which is why I have this here
    }
}
catch
{
    // no content type properties found in this document
}

foreach (DocumentProperty prop in builtInDocProperties)
{
    try
    {
        htProperties.Add(prop.Name, prop.Value);
    }
    catch { }
}

foreach (DocumentProperty prop in customDocProperties)
{
    try
    {
        htProperties.Add(prop.Name, prop.Value);
    }
    catch { }
}

Now all the properties can be queried from the Hashtable htProperties.

For example, to get the title, you would use htProperties["Title"].ToString(). To get a custom property named "Favourite Colour", you would use htProperties["Favourite Colour"].ToString(). These properties are objects and need to be cast to the right variable type. Such as (DateTime)htProperties["BirthDate"].

To set the value of a property via code, you would need to know the name of the property and the type of property, be it a BuiltInDocumentProperty, a CustomDocumentProperty or a MetaProperty (content type property).

MetaProperty mp = contentTypeProperties["Favourite Colour"];
mp.Value = "Blue";

Feb 17

Usually most of my code is run on the server, meaning that the DLLs sit on the server. This means that I can use the Microsoft.SharePoint DLL to query SP lists, SP document libraries, and so on.

My last project required me to code a Word Add-in. This is a client side application that required a connection to SharePoint to query a SP list. This means that I am no longer able to use Microsoft.SharePoint DLL to query the list as that is only for server side code. I was aware that I had to use the Microsoft.SharePoint.Client and Microsoft.SharePoint.Client.Runtime DLLs but they did not exist in the .NET references list, so I was not able to add them (the list is filtered based on the type of app you are writing).

I did notice that the filter was set to ".NET Framework 4 Client Profile". I modified that to ".NET Framework 4" (in the Project Properties) and was then able to add the required DLL references.

The code to query the list on the client side is also quite different to querying the list on the server side.

Here's the code to query a list on the client side:

using SP = Microsoft.SharePoint.Client; // Make sure you have added the reference to Microsoft.SharePoint.Client
string sharePointSite = "http://intranet";
string siteName = "/site/subsite";
string listName = "MyListName";

SP.ClientContext ctx = new SP.ClientContext(sharePointSite + siteName);
var web = ctx.Web;
SP.List oList = web.Lists.GetByTitle(listName);

SP.CamlQuery oQuery = new SP.CamlQuery();
// the following query queries everything in the list ordered by ID and limited to 100 results
oQuery.ViewXml = "<View><Query><OrderBy><FieldRef Name='ID' Ascending='TRUE'/></OrderBy></Query><RowLimit>100</RowLimit></View>";
SP.ListItemCollection oListItems = oList.GetItems(oQuery);

ctx.Load(oListItems);

ctx.ExecuteQuery();

for (int i = 0; i < oListItems.Count; i++)
{
    SP.ListItem oListItem = oListItems[i];

    // do what you want with oListItem as it now contains the values in the list item.
}