Story Details for articles

OpenXml Word Table Generator Article

kahanu
Author:
Version:
Views:
10650
Date Posted:
7/15/2012 10:39:52 PM
Date Updated:
7/15/2012 10:39:52 PM
Rating:
0/0 votes
Framework:
ASP.NET MVC 3
Platform:
Windows
Programming Language:
C#, OpenXml
Technologies:
OpenXml, Ninject
Tags:
OpenXml, Microsoft Word
Demo site:
Home Page:
Share:
WordDataRowTableGenerator.zip
File: WordDataRowTableGenerator.zip - 6.19 MB | Downloads: 3539

OpenXml Microsoft Word Table Generator

This article demonstrates how to integrate the OpenXml framework into an ASP.NET MVC 3 web application to generate Word documents and insert a table with content controls into it, and then populate that table with data from a database.

ASP.NET MVC 3 application

For those who don't know, OpenXml is a framework that allows you to programmatically create Microsoft Office documents and manipulate various properties and operations.  A good place to get started with OpenXml is at this address: http://openxmldeveloper.org/.

Origin of this exercise

The reason I created this component in the first place was out of need.  I'm presently working on a project for a client where I had to build a web application that would allow my client to dynamically create Word documents, and some of them needed tables that would be populated with data from a database.

I did some tests and found that it wasn't all that hard to create a table in Word, add content control into the table cells that would be populated with data from a database.  The problem was that I soon realized that this project would required maybe 30 Word documents with custom tables.  Each table would be different and need to be populated with data from a different datasource.

I looked around for an open source solution somewhere for this and couldn't find one.  I did find a great framework for creating components that would be able to manipulate Word documents and populate them with data.

http://worddocgenerator.codeplex.com/

This framework built by Atul Verma helped me with the part of the project that would allow me to generate the Word documents and populate them with data.  I highly recommend downloading his framework if you are interested in Word automation.

I still needed a way to dynamically generate the tables quickly.  So I built it myself.

TableBuilder Component

This is what I call the component that can easily build the table to be inserted into a Word document.  In the downloadable source code, I show how it's a completely separate component that I've integrated into a console application and an ASP.NET MVC 3 application.

It simply does one thing, it creates a Word table from your definition.  You decide where in the document it is placed.

WordTableGenerator.Mvc

There are four projects for this ASP.NET MVC 3 application:
  1. WordTableGenerator.Mvc - this is the MVC application
  2. WordTableGenerator.BusinessObjects - these would be the domain objects as represented by your data entities.  There can also be ViewModels here that could be shared across all projects.
  3. WordTableGenerator.Services - these are the services used by the MVC controllers
  4. WordTableGenerator.ComponentFactory - this is the project that contains the various classes that handle the Word generation and insert the table

I've tried to build this little Mvc application in a real-world way so you can see how this would work in a working application. 

Visual Studio solution

For this demonstration, the data that populates the Word table for my example is simply hard coded into the KingsDocumentClient class in the component factory.

What does this application do?

I needed to make the process of creating Word documents with tables as easy as possible, and also easy for someone else to create them besides me.  So I built a one-step process to create the documents with the tables, and another step for populating them with data.

This is the web application home page. 

Default web app

It shows two links: Create New Document and Populate Document.  These links do exactly what they say.

There's also two labels, Generated Word Templates and Rendered Word Documents.  These are columns that will contain a list of documents that are either generated by this application, or populated with data from this application.

To create a new document with a Word table inserted into it, we click on the Create New Document link.

Create a new document - empty

In the Word Document Name field we enter the name of the document that will be created.  This will be the filename of the document and the title placed at the top of the created Word document.

In the Column Definitions field, enter the list of column names that will be generated inside the table.  This should be a comma-delimited list of names.

(For this working demonstration I've built only two datasources that can populate documents, so the document names and column definitions must match the values below.  You can create a new data source and a new document generator class to test this with.)

Values to be used for testing purposes:
  • "King's Document" - "First Name, Last Name, Email, Phone"
  • "Golf Course Document" - "Course Name, Slope, Rating, Yardage"

Enter the values above into the form to generate a new document with a table.  I will first create my "King's Document".

Create new King's Document

When I click the "Create Word Document" button, and no errors occur, I will be taken back to the home page.

King's document in list

Now a few things happened here.

  1. Column Definitions - the column definitions xml file was created
  2. Document created - the document was created with the Word table and saved in the Templates folder

king's files created in solution

This is the Xml definitions file that describes the columns based on the names entered into the form.

01.<?xml version="1.0" encoding="utf-8"?>
02.<columndefinitions tablecontentcontrolname="KD">
03.  <headings>
04.    <heading>First Name</heading>
05.    <heading>Last Name</heading>
06.    <heading>Email</heading>
07.    <heading>Phone</heading>
08.  </headings>
09.  <rowcontainer title="KDDetailRow" tag="KDDetailRow">
10.    <columns>
11.      <column title="FirstName" tag="FirstName" />
12.      <column title="LastName" tag="LastName" />
13.      <column title="Email" tag="Email" />
14.      <column title="Phone" tag="Phone" />
15.    </columns>
16.  </rowcontainer>
17.</columndefinitions>

You can see that the Title of the document, "King's Document" was trimmed to "KD" and placed in various positions in the Xml.  This is because in Microsoft Word, the Alias and Tag fields for the content controls only hold 63 characters.  And for longer file names (titles), this can pose a problem, so I reduced that to use just the first character from each word in the title.

It also removes the spaces between words like "First Name" for the content control values.

It's this file that the TableBuilder component will use to generate the table cells for the table.

I'll click on the link of the generated file and take a look at the generated Word document. We'll see that it's created as we expected with the Title at the top of the page and the table created below it.

king generated word doc

Now this document is ready to be populated with data from a database.

For this we can click the "Populate Document" link.  When we do we see the following page:

Populate King's document

I've only created one Word template, "King's Document", so only one choice appears in the drop down.  But for this demonstration I've already created two datasources, one for this document and another for the second example I show you shortly.

When I click on the "Populate Document" button with the two King's Document values selected, the Word template will be used to create a new Word document that will be populated with data.  We will then be redirected back to the home page.

Home page and King's rendered doc

Now if I click on this new link for the rendered document we will see the table is fully populated with data.

King's rendered document

If we look back in Visual Studio we can see that the rendered document now exists in the folder.

King's rendered document

Now I'll create one more document template and populate it with completely different data to show how flexible this can be.

I'll create a new document.

create new golf course document

We can see that the new Word template has been successfully created.

Home page with golf course document

This is the Xml column definitions file.

01.<?xml version="1.0" encoding="utf-8"?>
02.<columndefinitions tablecontentcontrolname="GCD">
03.  <headings>
04.    <heading>Course Name</heading>
05.    <heading>Slope</heading>
06.    <heading>Rating</heading>
07.    <heading>Yardage</heading>
08.  </headings>
09.  <rowcontainer title="GCDDetailRow" tag="GCDDetailRow">
10.    <columns>
11.      <column title="CourseName" tag="CourseName" />
12.      <column title="Slope" tag="Slope" />
13.      <column title="Rating" tag="Rating" />
14.      <column title="Yardage" tag="Yardage" />
15.    </columns>
16.  </rowcontainer>
17.</columndefinitions>

You can see that this could be tedious to manually create for every table you wanted to create.  Automation is a truly great thing!

This is the newly created golf course Word template.

Golf course Word template

Now I'll populate it with data.  (Again, I've already included a component that has static data that will populate the template with data.)  I'll click on the "Populate Document" button.

Now I have two selections in each drop down, and I'll choose the Golf Course items in both.

Populate Golf Course document

This is the home page with the links to all the documents.

Home page with all the document links

Here's a look at the populated Golf Course Word document.

Golf course rendered Word document

That's it! 

Summary

In just a few steps you are able to create a Word document with a table that contains content controls that are used to be populated with data from a datasource, and populate it.

Look at the ComponentFactory project to see what I did to incorporate the WordDocumentGenerator.Library assembly into the project to create the documents and templates, and how I created a simple factory to make it easy to add your own classes.

I hope you found this article and the associate video helpful.

Comments

  • hammadi.ksiaa@gmail.com
    Posted By: KPENZA
    On: 9/5/2013 5:12:53 AM

    Thank youforthis tutorial,

    I havealmostthe same needwiththeability to attachthe document tothe application fromthe Officeinterface.

    Can you help me?

  • hammadi.ksiaa@gmail.com
    Posted By: KPENZA
    On: 9/5/2013 7:26:45 AM
    Thank youforthis tutorial,
    I havealmostthe same needwiththeability to attachthe document tothe application fromthe Officeinterface.
    Can you help me
  • info@kingwilder.com
    Posted By: king wilder
    On: 9/5/2013 9:11:46 AM
    @kpenza - you would have better luck going to http://www.openxmldeveloper.org for help.
  • ooooo
    Posted By: ooo
    On: 7/15/2015 3:08:27 AM
    ggggggg
  • rahulgupta227@gmail.com
    Posted By: rahul
    On: 1/24/2016 10:31:39 PM
    sfdfs
  • nickluu73@yahoo.com.au
    Posted By: nickluu73
    On: 3/1/2016 6:19:14 PM

    I got error to open the solution. 

    C:\Users\nluu0\Downloads\WordDataRowTableGenerator (1)\WordDataRowTableGenerator\TableGenTests\TableGenTests.csproj : error  : The project file 'C:\Users\nluu0\Downloads\WordDataRowTableGenerator (1)\WordDataRowTableGenerator\TableGenTests\TableGenTests.csproj' cannot be opened.


    The project type is not supported by this installation.


    C:\Users\nluu0\Downloads\WordDataRowTableGenerator (1)\WordDataRowTableGenerator\WordTableGenerator.Mvc\WordTableGenerator.Mvc.csproj : error  : The project file 'C:\Users\nluu0\Downloads\WordDataRowTableGenerator (1)\WordDataRowTableGenerator\WordTableGenerator.Mvc\WordTableGenerator.Mvc.csproj' cannot be opened.


    The project type is not supported by this installation.

  • info@kingwilder.com
    Posted By: King Wilder
    On: 3/2/2016 7:43:34 AM
    @nickluu73 - it probably has to due with the fact that it was made with VS 2010 and there may be differences in the way the application is loaded in VS 2013 or later.  You might need to go into the .csproj file and make adjustments.

 

User Name:
(Required)
Email:
(Required)