How to create a Word document from a template (.dotx) using Open XML SDK

One of the needs to use Open XML SDK is to create a document on server side. Creating a Word document from scratch using Open XML SDK is very tedious especially when it contains styles and themes. It is a good idea to create a document manually and then create a copy from this document and modify its content. A sample code that does the same is given below:

System.IO.File.Copy(sourceFile, destinationFile);
using (WordProcessingDocument document = WordProcessingDocument.Open(destinationFile, true))
{
   // Code to modify the document
}

However, this is not straight forward when it comes to create a document from an existing template (.dotx) file. The matter can be worse when a user wants to maintain the connection to the template in the newly created document (which is similar when we create a document from a template manually).

The following steps briefs how to create a document from a template using Open XML SDK and attach it to the document.

  1. Create a copy of the template and open it for editing
  2. Change the document type to WordProcessingDocumentType.Document
  3. Create an AttachedTemplate object
  4. Append the AttachedTemplateobject to the DocumentSettingsPart.Settings.
  5. Add an External Relationship of type AttachedTemplate to the DocumentSettingsPart.Settings.
  6. Save the document.

I will explain each step with the code.

The first step is to create a copy of the template and open it for editing. We can use System.IO.File.Copy() method to create a copy. Once the copy is created, use WordProcessingDocument.Open() method to open the file for editing. Consider we have a template with the name Sample.dotx on the current directory from which we need to create the document.

string sourceFile = Path.Combine(Environment.CurrentDirectory, “Sample.dotx”);
string destinationFile = Path.Combine(Environment.CurrentDirectory, “SampleDocument.docx”);
using(WordProcessingDocument document = WordProcessingDocument.Open(destinationFile, true))
{
// Rest of the code
}

Even though the extension of the destinationFile is “docx”, it is still a template. We need to change the document type using ChangeDocumentType() method

document.ChangeDocumentType(WordProcessingDocumentType.Document);

The next step is to create an AttachedTemplate object and assign a relationship id to it. Assigning the relationship id is important because, the document will identify the attached template using this id.

AttachedTemplate attachedTemplate1 = new AttachedTemplate() { Id = “relationId1”};

Now we can append the AttachedTemplate to the DocumentSettingsPart as given below:

MainDocumentPart mainPart = document.MainDocumentPart;
DocumentSettingsPart documentSettingsPart1 = mainPart.DocumentSettingsPart;
documentSettingsPart1.Settings.Append(attachedTemplate1)

It is not over yet. An essential step is to add an external relationship of type AttachedTemplate and specify the URI of the document template from which the document is created. Do not forget to add the relationship id that we previously specified for AttachedTemplate object.

documentSettingsPart1.AddExternalRelationship("http://schemas.openxmlformats.org/officeDocument/2006/relationships/attachedTemplate", new Uri(sourceFile, UriKind.Absolute), "relationId1");

Now you can add other code to modify the document and then save it. The complete code is given below:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using DocumentFormat.OpenXml.Wordprocessing;
using DocumentFormat.OpenXml.Packaging;
using System.IO;

namespace GenerateDocumentFromTemplate
{
    class Program
    {
        static void Main(string[] args)
        {
            string destinationFile = Path.Combine(Environment.CurrentDirectory, "SampleDocument.docx");
            string sourceFile = Path.Combine(Environment.CurrentDirectory, "Sample.dotx");
            try
            {
                // Create a copy of the template file and open the copy
                File.Copy(sourceFile, destinationFile, true);
                using (WordprocessingDocument document = WordprocessingDocument.Open(destinationFile, true))
                {
                    // Change the document type to Document
                    document.ChangeDocumentType(DocumentFormat.OpenXml.WordprocessingDocumentType.Document);

                    // Get the MainPart of the document
                    MainDocumentPart mainPart = document.MainDocumentPart;

                    // Get the Document Settings Part
                    DocumentSettingsPart documentSettingPart1 = mainPart.DocumentSettingsPart;

                    // Create a new attachedTemplate and specify a relationship ID
                    AttachedTemplate attachedTemplate1 = new AttachedTemplate() { Id = "relationId1" };

                    // Append the attached template to the DocumentSettingsPart
                    documentSettingPart1.Settings.Append(attachedTemplate1);

                    // Add an ExternalRelationShip of type AttachedTemplate.
                    // Specify the path of template and the relationship ID
                    documentSettingPart1.AddExternalRelationship("
http://schemas.openxmlformats.org/officeDocument/2006/relationships/attachedTemplate", new Uri(sourceFile, UriKind.Absolute), "relationId1");

                    // Save the document
                    mainPart.Document.Save();
                    Console.WriteLine("Document generated at " + destinationFile);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            { 
                Console.WriteLine("\nPress Enter to continue…");
                Console.ReadLine();
            }
        }
    }
}

I will add more entries on Open XML. Let me know if you have any queries.