WordDocGenerator is an utility to generate Word documents from templates using Visual Studio 2017, .NET Framework 4.7 and DocumentFormat.OpenXml 2.8.1. WordDocGenerator helps generate Word documents both non-refresh-able as well as refresh-able based on predefined templates using minimum code changes. Content controls are used as placeholders for document generation.
I had created this utility a few years back and you can read more details by going through older blogs which are still relevant (other than Charts which have been removed).
Document-level customizations for Word 2007 and Word 2010
One of the ways to “Refresh the document from within the Word(e.g. right click on document and click Refresh) using document-level customizations for Word 2007 and Word 2010“
This post will focus on Charts. I’ve added the samples to generate/refresh charts using OpenXML. The screenshot below displays the template having Scatter chart and Line chart and the document generated out of this template using this utility.
Word 2010 Template having Charts –> Generated documents with Charts refreshed:
Code Changes:
Class diagram for Chart specific classes is displayed below
“SampleDocumentWithTableAndChartsGenerator” is the sample that shows how to refresh template having Scatter and Line charts. The code snippets are displayed below
“RefreshCharts” method is added to DocumentGenerator class
/// <summary>
/// Refreshes the charts.
/// </summary>
/// <param name="mainDocumentPart">The main document part.</param>
List of functionalities that can be achieved using the utility/source code
Description regarding Samples provided with utility
New samples added in this update
In this part I’ll discuss about the sample that shows one of the ways to “Refresh the document from within the Word(e.g. right click on document and click Refresh) using document-level customizations for Word 2007 and Word 2010“. On click of Refresh Document the content of the document is refreshed as displayed below
Project “WordDocumentGenerator.WordRefreshableDocumentAddin” has been added to the utility for this sample. The steps followed for creating this sample are listed below
Added a new Word 2010 Document project as displayed below
Updated the document by adding the content controls as displayed below
Added a new Command bar button i.e. “Refresh Data” to the Command bar. On click of this button the document will be refreshed. The common scenario will be to refresh data from the Service. “WordDocumentGenerator.WordRefreshableDocumentAddin” is the document level customization project. This project references “WordDocumentGenerator.Library” and “WordDocumentGenerator.Client” projects.
The code snippet to add a new Command bar button is
This is the second post of this series. The previous post can be read at Part 1. The next post can be read at Part 3. The code is available for download at Utility Source Code.
Document generation using Content Controls and Open XML 2.0 SDK
Creating Word templates
Implementation and Samples
In Part 3 I have explained one of the way to “Refresh the document from within the document(e.g. right click on document and click Refresh) using document-level projects for Word 2007 and Word 2010“
In this post I’ll discuss
List of functionalities that can be achieved using the utility/source code
Description regarding Samples provided with utility
New samples added in this update
The sample document generators are discussed later. The functionalities that can be achieved using the utility/source code are: Document Generation
Generate document from a Word template using content controls as place holders and populate controls with data(Object)[SampleDocumentGenerator, SampleRefreshableDocumentGenerator, SampleDocumentWithTableGenerator]
Generate document from a Word template using content controls as place holders(data bound content controls) and populate controls with data(Object is serialized to Xml). [SampleDocumentGeneratorUsingDatabinding, SampleDocumentWithTableGeneratorUsingDatabinding, SampleDocumentGeneratorUsingXmlAndDatabinding]
Generate document from a Word template using content controls as place holders and populate controls with data(XmlNode)[SampleDocumentGeneratorUsingXml]
Generate document from a Word template using content controls as place holders(data bound content controls) and populate controls with data(XmlNode) [SampleDocumentGeneratorUsingXmlAndDatabinding]
Refresh the document from within the document(e.g. right click on document and click Refresh) using document-level projects for Word 2007 and Word 2010 [Explained in next post i.e. Part 3]
Generate document that can be
Standalone: Once generated document cannot be refreshed.
Refreshable: Once generated document can be refreshed. Content controls will be added/updated/deleted and content control’s content will be refreshed as per data.
Append documents using AltChunk
Protect Document
UnProtect Document
Removal of Content Controls from a document while keeping contents
Removal of Foot notes
Ensuring the each content control has unique Id’s by fixing the duplicate Id’s if any for a document
Serializing an Object to Xml using XmlSerializer(Used for document generation using data bound content controls as serialized object is written to CustomXmlPart)
Content Controls
Set text of a content control(not applicable for data bound content controls)
Get text from a content control(not applicable for data bound content controls)
Set text of content control while keeping PermStart and PermEnd elements(not applicable for data bound content controls)
Set Tag of a content control
Get Tag of a content control
Set data binding of a content control
Set text of a data bound content control from CustomXmlPart manually. This is helpful in cases when CustomXmlPart needs to be removed and this copies the text from the CustomXmlPart node using XPath.
CustomXmlPart
Adding a CustomXmlPart to a document
Removing CustomXmlPart from a document
Getting CustomXmlPart from a document
Add/Update a Xml element node inside CustomXmlPart. This is required
To keep Document related metadata e.g. Document type, version etc.
To make the Document self-refreshable. In this case the container content control is persisted inside a Placeholder node, the first time document is generated from template. Onwards when refreshing document we fetch the container content control from CustomXmlPart
Saving the Xml e.g. serialized object which will be the data store for data bound content controls
Sample Generators:
SampleDocumentGenerator: This sample shows how to generate a non-refreshable document from a template. The content controls are populated using C# code i.e. not using data bound content controls. It covers both direct assignment as well as recursive controls. The screenshot is
SampleRefreshableDocumentGenerator: This sample shows how to generate a refreshable document from a template. The content controls are populated using C# code i.e. not using data bound content controls. This is similar to SampleDocumentGenerator in implementation. Only difference is the generated document can be refreshed in this case. The screenshot is
SampleDocumentWithTableGenerator: This sample shows how to generate a refreshable document from a template having Table. The content controls are populated using C# code i.e. not using data bound controls. This is similar to to SampleRefreshableDocumentGenerator in implementation. Only difference is the template has an additional table. The screenshot is
SampleDocumentGeneratorUsingDatabinding: This sample shows how to generate a refreshable document from a template using data bound content controls. This requires that each of the placeholder(template’s content control) has a predefined XPath. The generated document is similar to SampleRefreshableDocumentGenerator.
SampleDocumentWithTableGeneratorUsingDatabinding: This sample shows how to generate a refreshable document from a template having table using data bound content controls. This requires that each of the placeholder(template’s content control) has a predefined XPath. The generated document is similar to SampleDocumentWithTableGenerator.
SampleDocumentGeneratorUsingXml (New): This sample shows how to generate a document from a template using XmlNode as data. This approach shows that a generic generator can be created which requires Xml as data. This requires that XPath for Tag as well as content needs to be provided. The content controls are populated using C# code i.e. not using data bound controls. It covers both direct assignment as well as recursive controls. The generated document is similar to SampleDocumentGenerator.
SampleDocumentGeneratorUsingXmlAndDatabinding (New): This sample shows how to generate a document from a template using XmlNode as data and data bound content controls. This approach shows that a generic generator can be created which requires Xml as data. This requires that XPath for Tag as well as content needs to be provided. It covers both direct assignment as well as recursive controls. The generated document is similar to SampleDocumentGenerator.
List of functionalities that can be achieved using the utility/source code
Description regarding Samples provided with utility
New samples added in this update
In Part 3 I have explained one of the way to “Refresh the document from within the document(e.g. right click on document and click Refresh) using document-level projects for Word 2007 and Word 2010“
The purpose of creating this utility was to use the Open Xml 2.0 SDK to generate Word documents based on predefined templates using minimum code changes. These documents can either be refreshable or non- refreshable. I’ll explain this difference later. Also there is no dependency that Word should be installed.
A few samples for generating Word 2010 documents have been provided. The screenshots below display the sample template and the document generated out of this template using this utility.
Word 2010 Template –> Generated Document:
Word 2010 Template –> Generated Document –> Refreshed Document:
Document Refresh from within Word –> Refreshed Document:
Template Design:
The sample templates are inside “WordDocumentGenerator.Client\Sample Templates” folder. A content control as displayed below can have Title and Tag properties.
The logic is to have a tag property of a content control and then populate data using that placeholder. This means every content control inside a Word template will have a different Tag.
As per image above the tag of the content control is “PlaceholderNonRecursiveB”. During document generation we can assign (not mandatory) a unique Id e.g. Guid of a record to make the tag unique e.g. “PlaceholderNonRecursiveB:Guid”. Let’s say that we have an Id and Name field. Thus the Name will be the content of the control and tag will be “PlaceholderNonRecursiveB:Id”. As per Word 2010 the Tag maximum length is 64.
In code we map the tag to the PlaceHolderType enum.
public enum PlaceHolderType
{
None = 0,
Recursive = 1,
NonRecursive = 2,
Ignore = 3,
Container = 4
}
There can be multiple types of PlaceHolders
Recursive: This type corresponds to controls where there is 1:N relation between template and data i.e. one example will be repeating a list of Items.
Non-Recursive: This type corresponds to controls where there is 1:1 relation between template and data i.e. one example will be showing a User name.
Ignore: No action is required for these controls.
Container: This type is required only for refreshable documents. We save the container region in CustomXmlPart the first time document is generated from template. Next time onwards we retrieve the container region that was saved and refresh the document. This makes the document self-refreshable.
I’ve named the tags in “Test_Template – 1.docx” as per their PlaceHolder type to make it more clear.
Implementation:
As explained above the Tag property will used to bind data to this content control. The project “WordDocumentGenerator.Library” is the utility library. The project “WordDocumentGenerator.Client” shows how this library can be used to generate documents.
“DocumentGenerator” is the base class that needs to be inherited by the document generators. The sample generators location is “WordDocumentGenerator.Client\Sample Document Generators”.
The purpose of creating this utility was to use the Open Xml 2.0 SDK to generate Word documents based on predefined templates using minimum code changes. These documents can either be refreshable or non- refreshable. New samples will be added as per feedback.