SharePoint Blogs / SharePoint University
SharePoint Blogs and SharePoint University - all in one place!
Need SharePoint Training? Attend a SharePoint Bootcamp!

Please delete cookies related to sharepointblogs.com and sharepointu.com to resolve login issues!

Display Version and Other SharePoint Metadata in Word 2003 Documents

You can view and edit text columns from a document library from a Word 2003 document. For example: 

DocProperties

This is a great integration point between Office and SharePoint, but there are a couple a gotcha's you should be aware of, and the following very reasonable and realistic requirements for a document management solution will highlight them.

  1. The version and author from SharePoint should be displayed in the header of Word 2003 documents in the document library
  2. The version and author from SharePoint should be updated automatically when users open or print documents from the document library

The first issue is that only SharePoint text columns can be synchronized into Word document properties.  Version is not a text column.  The second issue is that the fields used to display the metadata in Word are not updated automatically when opening or printing the document.  I will present a solution (or workaround) for both issues, but first let's examine how the integration works.

When a Word document is created from or uploaded to a SharePoint document library, text columns are copied to Word document properties.  SharePoint will create the document properties for you when the document is first added, but not when it is updated.  You can always manually add a document property if you need to--just make sure the name exactly matches the SharePoint text column name.

Here's a simple example to illustrate the integration.

Add a text column to your document library:

CreateColumn

For testing purposes, edit one of the document library items and enter some text in the custom column:

ModifyCustomColumn

Now open the document in Word 2003 and examine the document properties.  Select File...Properties.  If you see the following dialog, click on File Properties.

FileProperties

Click on the Custom tab and note that the MyCustomColumn document property exists and contains the text from the SharePoint list item.

MyCustomColumnDocProperty

To demonstrate the metadata is two-way, edit the value of MyCustomColumn (the UI is slightly cloogy here).  Click on the MyCustomColumn in the bottom list.  Enter a value in the Value field and then click the Modify button:

ModifyCustomColumnInWord

Save the document back to SharePoint and notice the column is updated.  This is great if want two-way updates, but bad if you want it to be read-only in Word.

MyCustomColumnDocPropertyInSP

In order to display the version number, we need a text column that contains the version number.  One way to accomplish this is to use an event handler to copy the version number to a read-only text column.  Here is the code for the event receiver.  I'll leave it to you how you want to deploy the event receiver but a simple way is write a program to register the event receiver on the document library.

    //****************************************************************
    /// DocumentVersionEventReciever
    /// <summary>
    /// An event receiver to provide a custom version number
    /// text field that can be displayed in Word 2003.
    /// </summary>
    //****************************************************************
    public class DocumentVersionEventReciever : SPItemEventReceiver
    {
        #region Constants

        private const string FIELD_DOC_VERS = "DocumentVersion";
        private const string FIELD_ITEM_VERS = "Version";

        #endregion Constants

        #region Methods

        //****************************************************************
        /// SetDocumentVersion
        /// <summary>
        /// Copies the document version to a text field so it can be
        /// sychronized with a Word property.
        /// </summary>
        /// <param name="item"></param>
        //****************************************************************
        private void SetDocumentVersion(SPListItem item)
        {
            item[FIELD_DOC_VERS] = item[FIELD_ITEM_VERS];
            item.SystemUpdate(false);

        } // end SetDocumentVersion()

        //****************************************************************
        /// DeleteDocumentVersionField
        /// <summary>
        /// Deletes the document version field.
        /// </summary>
        /// <param name="list"></param>
        //****************************************************************
        private void DeleteDocumentVersionField(SPList list)
        {
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                list.Fields[FIELD_DOC_VERS].ReadOnlyField = false;
                list.Fields[FIELD_DOC_VERS].Update();
                list.Fields[FIELD_DOC_VERS].Delete();

                // Check
                if (list.Fields.ContainsField(FIELD_DOC_VERS))
                    throw new ApplicationException("Failed to delete field '" + FIELD_DOC_VERS + "'.");

            }); // end run with elevated

        } // end DeleteDocumentVersionField()

        //****************************************************************
        /// CreateDocumentVersionField
        /// <summary>
        /// Creates the document Version field.
        /// </summary>
        /// <param name="list"></param>
        //****************************************************************
        private void CreateDocumentVersionField(SPList list)
        {
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                list.Fields.Add(FIELD_DOC_VERS, SPFieldType.Text, false);
                SPField fld = list.Fields[FIELD_DOC_VERS];
                fld.ReadOnlyField = true;
                fld.Update();
                list.Update();

                // Check
                if (!list.Fields.ContainsField(FIELD_DOC_VERS))
                    throw new ApplicationException("Failed to create field '" + FIELD_DOC_VERS + "'.");

                // Populate existing Versions
                foreach (SPListItem liExisting in list.Items)
                {
                    SetDocumentVersion(liExisting);
                }

            }); // end run with elevated

        } // end CreateDocumentVersionField()

        //****************************************************************
        /// SetDocumentMetaData
        /// <summary>
        /// Sets document metadata.
        /// </summary>
        /// <param name="properties"></param>
        //****************************************************************
        private void SetDocumentMetaData(SPItemEventProperties properties)
        {
            try
            {
                // Prevent triggering of other events
                this.DisableEventFiring();

                SPListItem li = properties.ListItem;
                SPList list = properties.ListItem.ParentList;

                //DeleteDocumentVersionField(list);

                // Add field if doesn't exist
                if (!list.Fields.ContainsField(FIELD_DOC_VERS))
                {
                    CreateDocumentVersionField(list);
                }
                else
                {
                    SetDocumentVersion(li);
                }
            }
            catch (Exception ex)
            {
                properties.ErrorMessage = ex.Message;
            }
            finally
            {
                // Enable triggering of other events
                this.EnableEventFiring();
            }

        } // end SetDocumentMetaData()

        #endregion Methods

        #region Event Handlers

        //****************************************************************
        /// ItemUncheckedOut
        /// <summary>
        /// The event that occurs when an item is checked out.
        /// </summary>
        /// <param name="properties"></param>
        //****************************************************************
        public override void ItemUncheckedOut(SPItemEventProperties properties)
        {
            SetDocumentMetaData(properties);

        } // end ItemUncheckedOut()

        //****************************************************************
        /// ItemCheckedOut
        /// <summary>
        /// The event that occurs when an item is checked out.
        /// </summary>
        /// <param name="properties"></param>
        //****************************************************************
        public override void ItemCheckedOut(SPItemEventProperties properties)
        {
            SetDocumentMetaData(properties);

        } // end ItemCheckedOut()

        //****************************************************************
        /// ItemCheckedIn
        /// <summary>
        /// The event that occurs when an item is checked in.
        /// </summary>
        /// <param name="properties"></param>
        //****************************************************************
        public override void ItemCheckedIn(SPItemEventProperties properties)
        {
            SetDocumentMetaData(properties);

        } // end ItemCheckedIn()

        //****************************************************************
        /// ItemUpdated
        /// <summary>
        /// The event that occurs when an item is updated.
        /// </summary>
        /// <param name="properties"></param>
        //****************************************************************
        public override void ItemUpdated(SPItemEventProperties properties)
        {
            SetDocumentMetaData(properties);

        } // end ItemUpdated()

        //****************************************************************
        /// ItemAdded
        /// <summary>
        /// The event that occurs when an item is added to the list.
        /// </summary>
        /// <param name="properties">Properties about the item</param>
        //****************************************************************
        public override void ItemAdded(SPItemEventProperties properties)
        {
            SetDocumentMetaData(properties);

        } // end ItemAdded()

        #endregion EventHandlers
    }

You can see that the event receiver is ensuring the text column DocumentVersion always has the latest copy of the version number.  I do have a criticism of this code, and that is the creation of the column by the event receiver.  In a production envrionment, I would recommend creating a feature that creates a content type and hooks an event receiver to that content type.

Insert the DocumentVersion field in the document header (or wherever you want the version to appear).  From the menu, select Insert..Field.  Find the DocProperty field name and then select the DocumentVersion field property.

DocumentMetadata

The version will appear in the document, and that leads into the next issue.  The field won't update until the user clicks on the field and selects Update Field.  (There is also an option you can set to update fields before printing, but as you recall, the requirement is to display the current version number when the document opens).

To illustrate the issue, check out the document in SharePoint and check it back in (or publish a major version).  Then open the document in Word.  You will see the field displays the old version number.  If you access the DocumentVersion property, you will see it has the correct value and the field just needs to be updated.  We are going to solve that issue with a Macro.

In Word, select Tools...Macros...Macro.  Then click on Create to create a new Macro.  Name the macro AutoOpen, and place the following code in the editor:

Sub AutoOpen()
    With Options
        .UpdateFieldsAtPrint = True
        .UpdateLinksAtPrint = True
    End With
    ActiveDocument.Fields.Update
End Sub

This code is setting the option to update fields and links before printing.  More importantly, it is updating all fields when the document opens.  You have a couple of choices for deploying this.  I'd recommend making this document the template for the document library.  That way, if users create documents from the document library, the properties, fields and macro is all setup.

I would caution you to set users expectations with this solution / workaround.  If they upload documents from outside SharePoint they obviously will not have the fields set up in the Word document to display the version number.  They also will not have the macro.

I hope you find this solution helpful for your Office 2003 users.


Posted 07-13-2007 6:16 AM by John Powell, PMP, MCPD, MCSD

Comments

Nadeem wrote re: Display Version and Other SharePoint Metadata in Word 2003 Documents
on 07-13-2007 10:51 AM

Excellent post!

Blog del CIIN wrote WSS 3.0 & MOSS: Recopilación de enlaces interesantes (IV)
on 07-24-2007 7:15 AM

Siguiendo con la recopilación periódica de recursos sobre WSS 3.0 &amp; MOSS, esta semana en el número

Carl Drehlich wrote re: Display Version and Other SharePoint Metadata in Word 2003 Documents
on 11-07-2007 8:49 PM

I am very new to Sharepoint and I am having alot of problems with your instructions. Is it possible for you to just post the solution so I can install it. It is exactly what I need.

Kunal wrote re: Display Version and Other SharePoint Metadata in Word 2003 Documents
on 12-06-2007 12:54 AM

Its a great tutorial thanks

Markus Kersting wrote re: Display Version and Other SharePoint Metadata in Word 2003 Documents
on 01-10-2008 7:25 AM

Excellent Work! Thanx. We came to the same solution after a long struggle. In addition: When you want to always update the Fields (we needed that) on opening the document, you have to implement an global AddIn for Word. For that put an ".dot" in Word's Startup-Folder, with the following VBA-Code in it. Security has to be low. Unfortunalty even is Security is low, this isn't executet when opened from Hyperlink, not via Sharepoint-Menu. This seems to be an general Security-Problem, we haven't solved. Maybe someone knows ..?

' --------------------------------------------------------

' VBA-Marko: Update Fields on Every Doc-Change

' --------------------------------------------------------

Option Explicit

Sub AutoExec()

 Call MsgDocChange

End Sub

Sub MsgDocChange()

 If Documents.Count > 0 Then

' alle felder aktualisieren

Dim rngDoc As Range

Dim oDoc As Document

Dim docSec As Section

Dim oHF As HeaderFooter

Dim shp As Shape

Set oDoc = ActiveDocument

For Each docSec In oDoc.Sections

 For Each oHF In docSec.Headers

   For Each shp In oHF.Shapes

       With shp.TextFrame

         If .HasText Then

           .TextRange.Fields.Update

         End If

       End With

   Next shp

 Next oHF

 For Each oHF In docSec.Footers

   For Each shp In oHF.Shapes

       With shp.TextFrame

         If .HasText Then

           .TextRange.Fields.Update

         End If

       End With

   Next shp

 Next oHF

 For Each rngDoc In oDoc.StoryRanges

   rngDoc.Fields.Update

   While Not (rngDoc.NextStoryRange Is Nothing)

     Set rngDoc = rngDoc.NextStoryRange

     rngDoc.Fields.Update

   Wend

 Next rngDoc

Next docSec

Set rngDoc = Nothing

Set oDoc = Nothing

 End If

End Sub

Markus Kersting wrote re: Display Version and Other SharePoint Metadata in Word 2003 Documents
on 01-10-2008 8:10 AM

Nachtrag VBA:

Dazu muss natürlich noch ein Klassen-Modul names "ThisApplication" in der ".dot" existieren mit diesem Code:

' ------------------------------------------------

' VBA - This-Application- Code

' ------------------------------------------------

Option Explicit

Public WithEvents wdAppl As Word.Application

Private Sub wdAppl_DocumentChange()

 Call MsgDocChange

End Sub

Sigi Frenkenberger wrote re: Display Version and Other SharePoint Metadata in Word 2003 Documents
on 01-17-2008 8:47 AM

Dear All!

I tried out another solution, but as I did not yet test intensively, maybe somebody can provide directly some pros and cons.

I have created a label that contains the version.

In this case a custom doc property named  "DLCPolicyLabelValue" has been created. I use this proterty now in my word document fields.  As long as I don't store the document in docx but in doc format, it seems to be working.

Thanx in advance for any comments.

felix wrote re: Display Version and Other SharePoint Metadata in Word 2003 Documents
on 05-15-2008 2:45 AM

I'm have take your code and make an dll file.

But how do I make the dll to run on the server, and how do I make to hole code to run when I save I word doc ??

MB wrote re: Display Version and Other SharePoint Metadata in Word 2003 Documents
on 05-23-2008 6:07 AM

In the word 2007 document in the Sharepoint I want to have a label to save the version of the document. When I opend the document so it can show the version of it selves. Maybe someone knows ..?

erugalatha wrote re: Display Version and Other SharePoint Metadata in Word 2003 Documents
on 05-28-2008 5:56 AM

Hi,

When adding sharepoint lookup columns as document properties on a template the index in the list is displayed rather than the Title of the item in the dropdown list.

Is there a way around this?

Ken Hayden wrote re: Display Version and Other SharePoint Metadata in Word 2003 Documents
on 05-30-2008 7:30 AM

I run Office 2007. Changing the properties in a .docx does not propagate to the server but it does when operating in compatible mode for a .doc

What is wrong in Office 2007?

RonP wrote re: Display Version and Other SharePoint Metadata in Word 2003 Documents
on 09-08-2008 1:44 PM

I have added a label using the information managment policy settings in the library using Sharepoint 2007 (but have Word 2003), but the label does not appear on the previewed or printed documents (even new ones after the label was created).  Note that the label fields are both recognized by Sharepoint and Word..  

I do not want to add the fields to the header manually.  What needs to be done to fix this?

Peeter wrote re: Display Version and Other SharePoint Metadata in Word 2003 Documents
on 10-21-2008 6:28 AM

Here were several interesting issues for us to read, and I hope they will continue to be covered and answered :-)

TSpann wrote re: Display Version and Other SharePoint Metadata in Word 2003 Documents
on 11-11-2008 3:53 PM

Hello

erugalatha,

I have had the same issue.  I can't seem to get the data listing from the dropdown in the word template to insert the actual data from the share point list.  Only the index number.  

Has anyone found an answer for this?

Ecrire dans un site SharePoint | hilpers wrote Ecrire dans un site SharePoint | hilpers
on 01-18-2009 5:57 AM

Pingback from  Ecrire dans un site SharePoint | hilpers

Prem wrote re: Display Version and Other SharePoint Metadata in Word 2003 Documents
on 01-29-2009 6:50 AM

Hello...

I have tried the version number and its working fine for one Document List. My Question is .. is there any option for make this version for all document list with out registering event seperately

CLeo wrote re: Display Version and Other SharePoint Metadata in Word 2003 Documents
on 06-19-2009 8:29 AM

Excellent, I tried in Word 2007 without any result. I didn't succed to add this new field, but don't worry guess i'd made some errors. Could you give me a code sample in VBA (not in .NET or otherelse) reffer at how can access the server properties (Version History exactly) from a macro on a Word 2007 document.

audunms wrote re: Display Version and Other SharePoint Metadata in Word 2003 Documents
on 06-26-2009 5:15 AM

Hi,

do you know how to hide your custom columns when saving a new document in Word 2003? It's easy to hide them in Sharepoint, but it's a bit cumbersome for the user to see for example MyCustomColumn in the pop-up for document properties he gets the first time saving a document created from this template...

Add a Comment

(required)  
(optional)
(required)  
Remember Me?
Need SharePoint Training? Attend a SharePoint Bootcamp!
Posts (c) their respective authors. Everything else (c) 2009 SharePoint Experts, Inc.