SharePoint Event Handling – Property Promotion in Office

One of the big selling points for SharePoint 2007 is the ability to have MS Word automatically detect the fields that are set up in Sharepoint and make those values available within the document. This feature is called property promotion when SharePoint pulls the values from the Word doc and fills in the list fields with those values. The reverse, when SharePoint pushes the values defined in the list into the word document, is called property demotion. This works quite well, until you have an event handler that automatically sets the value of a field in SharePoint.  Some problems you might encounter are…

  1. Property promotion sometimes occurs after you automatically set the field value, overwriting your value with a blank or whatever value was set in the document.
  2. Property demotion doesn’t include your auto-setting value.

I have only found one solution that works in all cases:

//Global variables to store values for the worker thread
private Guid ListID;
private Guid ItemID;
private Guid SiteID;
private String FieldValue;

public override void ItemUpdated(SPItemEventProperties properties){
    DisableEventFiring();

    try{
        //Store the values our thread is going to need to get a
        //handle on this list item.
        FieldValue = GetColumnValueForItem(properties.ListItem);
        ListID = properties.ListId;
        ItemID = properties.ListItem.UniqueId;
        SiteID = properties.SiteId;

        //Only start the new thread if it has NOT been set.
        if (uFieldValue != (string)properties.ListItem[COLUMN_NAME]){
             //Create the worker process
             Thread workerThread = new Thread(SetCustomValue);
             workerThread.Start();
        }
    }catch(){
        //Log error message.
    }

    EnableEventFiring();
}

public override void ItemAdded(SPItemEventProperties properties){
    DisableEventFiring();

    try(){
        //Store the values our thread is going to need to get a
        //handle on this list item.
        FieldValue = GetColumnValueForItem(properties.ListItem);
        ListID = properties.ListId;
        ItemID = properties.ListItem.UniqueId;
        SiteID = properties.SiteId;

        //Create the worker process
        Thread workerThread = new Thread(SetCustomValue);
        workerThread.Start();
    }catch(){
        //Log information about the error.
    }

    EnableEventFiring();
}

private void SetCustomValue(){
    try{
        //Wait for 5 seconds to allow all of the SharePoint
        //events to finish working.
        Thread.Sleep(5000);
        using (SPSite site = new SPSite(SiteID)){
            using (SPWeb web = site.OpenWeb()){
                //Get the list item using the global variables
                SPList list = web.Lists[ListID];
                SPListItem item = list.GetItemByUniqueId(ItemID);

                //Set the custom field to the proper value
                item[COLUMN_NAME] = uFieldValue;
                //Perform a SystemUpdate on the item to save
                //the changes to the field.
                item.SystemUpdate(false);
            }
        }
    }catch (Exception ee){
        //Log information about the error.
    }
}

The logic is fairly simple. Just spin up a thread that waits for SharePoint to be finished modifying the file and list item, then sets the auto field value. When this tactic is used, the auto value gets set in SharePoint and in the document for all reasonable test cases.  (i.e. when you copy using Word SaveAs to add a new document, when you use the Windows Explorer View, or when you use the standard SharePoint Web UI to Add or Edit the document.)  

One thing to keep in mind is that you can’t determine how many times the code will be run.  ItemAdded and Item Updating may each be called once, multiple times, or not at all, depending on what method was used to update the document.  So when the value of the custom field is calculated, you must use a formula that gives you the same result every time.

For more information, see the other posts in this series:

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: