Generating Documents from SharePoint Lists using Open XML Content Controls

It's often the case that a department manager needs to regularly send a nicely formatted status report to her general manager or that a team leader needs to send a weekly status report to a number of interested parties.  To collaborate with others in their organizations, both the manager and the team leader can maintain status information in SharePoint lists.  The question for developers is how to include the information in the lists in a document such as a status report.

This blog is inactive.
New blog: EricWhite.com/blog

Blog TOCI've written an article entitled Generating Documents from SharePoint with Open XML Content Controls, published in the October issue of MSDN Magazine that details how you can put together a simple, flexible, and powerful system for generating Open XML word-processing documents using SharePoint lists as sources for data in tables of word-processing documents.

The key aspect of a successful approach is to make it so that the folks who need to generate reports can do so without involving the services of a software developer.  We can adopt an approach where the user can configure the sources of data for tables in a document using content controls.  The user can surround a table with a content control, and set the content control tag to the name of the SharePoint list.  The user can insert content controls into cells in a nicely formatted table, and set the tags to the names of the columns of the SharePoint list.  We then have enough information to retrieve the necessary data from the SharePoint list (or lists) and generate a document that contains that data.  If the department manager or team leader subsequently adds a new column to their SharePoint list, they can add a new column to their table, insert a new content control, set the tag, and thereafter, their reports will contain data from the new column in the SharePoint list.

To make this clear, a typical SharePoint list looks like this:

The template Open XML word-processing document might look like the following.  Notice that there is a content control surrounding the entire table, with a tag and title of "Team Members", and there is a content control in a table cell with tag and title of "TeamMemberName".  If we were to put the insertion point in the Role cell, you would see that there is a content control there.  There are similar content controls around and in the Current Work Items table.

The resulting generated report looks like this:

One aspect of the approach that I took is that I abstracted the operations involving the content controls into a ContentControlManager class.  You can call a method, GetContentControls, which returns some XML that describes the content controls in the document.  In the example that I present with the article, GetContentControls returns the following XML:

<ContentControls>
<TableName="Team Members">
<FieldName="TeamMemberName" />
<FieldName="Role" />
</Table>
<TableName="Item List">
<FieldName="ItemName" />
<FieldName="Description" />
<FieldName="EstimatedHours" />
<FieldName="AssignedTo" />
</Table>
</ContentControls>

This gives us the information that we need to use the SharePoint object model to retrieve the necessary data.  After retrieving that data, we can construct a small XML tree that looks like this:

<ContentControls>
<TableName="Team Members">
<FieldName="TeamMemberName" />
<FieldName="Role" />
<Row>
<FieldName="TeamMemberName"
Value="Bob" />
<FieldName="Role"
Value="Developer" />
</Row>
<Row>
<FieldName="TeamMemberName"
Value="Susan" />
<FieldName="Role"
Value="Program Manager" />
</Row>
<Row>
<FieldName="TeamMemberName"
Value="Jack" />
<FieldName="Role"
Value="Test" />
</Row>
</Table>
<TableName="Item List">
<FieldName="ItemName" />
<FieldName="Description" />
<FieldName="EstimatedHours" />
<FieldName="AssignedTo" />
<Row>
<FieldName="ItemName"
Value="Learn SharePoint 2010" />
<FieldName="Description"
Value="This should be fun!" />
<FieldName="EstimatedHours"
Value="80" />
<FieldName="AssignedTo"
Value="All" />
</Row>
<Row>
<FieldName="ItemName"
Value="Finalize Import Module Specification" />
<FieldName="Description"
Value="Make sure to handle all document formats." />
<FieldName="EstimatedHours"
Value="35" />
<FieldName="AssignedTo"
Value="Susan" />”
</Row>
<Row>
<FieldName="ItemName"
Value="Write Test Plan" />
<FieldName="Description"
Value="Include regression testing items." />
<FieldName="EstimatedHours"
Value="20" />
<FieldName="AssignedTo"
Value="Jack" />
</Row>
</Table>
</ContentControls>

We can pass that XML to the SetContentControls method in the ContentControlManager class, which will modify the document so that the tables in the document are populated with the data from the XML.  This is useful functionality in its own right, and could be used in other scenarios than generating documents from SharePoint lists.

The MSDN article contains a download that contains the ContentControlManager class, as well as the SharePoint code to populate tables with data from SharePoint lists.