Adding Tables to Word 2010 Documents by Using the Open XML SDK 2.0

Office Visual How To

Summary:  Use the strongly typed classes in the Open XML SDK 2.0 to add a simple table to a Word 2007 or Word 2010 document, without loading the document into Microsoft Word.

Applies to: Excel 2010 | Office 2007 | Office 2010 | Open XML | PowerPoint 2010 | VBA | Word 2007 | Word 2010

Published:   December 2010

Provided by:   Ken Getz, MCW Technologies, LLC

Overview

The Open XML file formats make it possible to interact with and create tables in Microsoft Word documents, but doing this requires some effort. The Open XML SDK 2.0 adds strongly typed classes that simplify access to the Open XML file formats: The SDK simplifies the tasks of inserting information into a document. The code sample that is included with this Visual How To describes how to the use the SDK to achieve this goal.

Code It

The sample provided with this Visual How To includes the code that is required to insert a simple table into a Word 2007 or Word 2010 document. Figure 1 shows the table created by the sample application. The following sections discuss the code, in detail.

Figure 1. The sample application creates this simple table in an existing Word document.

Table that is added to a Word document

Setting Up References

To use the code from the Open XML SDK 2.0, you must add several references to your project. The sample project already includes these references, but in your own code, you would have to explicitly reference the following assemblies:

  • WindowsBase─This reference may be set for you, depending on the kind of project that you create.

  • DocumentFormat.OpenXml─Installed by the Open XML SDK 2.0.

In addition, you should add the following using/Imports statements to the top of your code file.

Imports DocumentFormat.OpenXml
Imports DocumentFormat.OpenXml.Packaging
Imports DocumentFormat.OpenXml.Wordprocessing
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;

Examining the Procedure

The WDAddTable procedure accepts two parameters that indicate:

  • The name of the document to modify (string).

  • A two-dimensional array of strings to insert into the document as a table.

Public Sub WDAddTable(ByVal fileName As String, 
                      ByVal data(,) As String)
public static void WDAddTable(string fileName, string[,] data)

The procedure modifies the document that you specify, adding a table at the end of the document that contains the information in the two-dimensional array that you provide. To call the procedure, pass both the parameter values, as shown in the example code. Verify that you provide a document named C:\temp\AddTable.docx before you run this sample code.

Const fileName As String = "C:\temp\AddTable.docx"
WDAddTable(fileName, New String(,) {
            {"Texas", "TX"},
            {"California", "CA"},
            {"New York", "NY"},
            {"Massachusetts", "MA"}})
const string fileName = @"C:\temp\AddTable.docx";
WDAddTable(fileName, new string[,] 
  { { "Texas", "TX" }, 
     { "California", "CA" }, 
     { "New York", "NY" }, 
     { "Massachusetts", "MA" } });

Accessing the Document

The code starts by opening the document by using the WordprocessingDocument.Open method and indicating that the document should be open for read-write access (the final true parameter). Next, the code retrieves a reference to the Document part by using the Document property of the MainDocumentPart property of the Word processing document.

Using document = WordprocessingDocument.Open(fileName, True)
  Dim doc = document.MainDocumentPart.Document
  ' Code removed here…
End Using
using (var document = WordprocessingDocument.Open(fileName, true))
{
  var doc = document.MainDocumentPart.Document;
  // Code removed here…
}

Creating the Table Object and Setting its Properties

Before you can insert a table into a document, create the Table object and set its properties. To set the table properties, create a supply values for a TableProperties object. The TableProperties class provides many table-oriented properties, such as Shading, TableBorders, TableCaption, TableCellSpacing, and TableJustification. The key is to specify the correct property values. The sample procedure includes the following code.

Dim table As New Table()

Dim props As TableProperties = _
  New TableProperties(New TableBorders( _
  New TopBorder With {
    .Val = New EnumValue(Of BorderValues)(BorderValues.Single),
    .Size = 12},
  New BottomBorder With {
    .Val = New EnumValue(Of BorderValues)(BorderValues.Single),
    .Size = 12},
  New LeftBorder With {
    .Val = New EnumValue(Of BorderValues)(BorderValues.Single),
    .Size = 12},
  New RightBorder With {
    .Val = New EnumValue(Of BorderValues)(BorderValues.Single),
    .Size = 12}, _
  New InsideHorizontalBorder With {
    .Val = New EnumValue(Of BorderValues)(BorderValues.Single),
    .Size = 12}, _
  New InsideVerticalBorder With {
    .Val = New EnumValue(Of BorderValues)(BorderValues.Single),
    .Size = 12}))
table.AppendChild(Of TableProperties)(props)
Table table = new Table();

TableProperties props = new TableProperties(
  new TableBorders(
    new TopBorder { 
      Val = new EnumValue<BorderValues>(BorderValues.Single), 
      Size = 12 },
    new BottomBorder { 
      Val = new EnumValue<BorderValues>(BorderValues.Single), 
      Size = 12 },
    new LeftBorder { 
      Val = new EnumValue<BorderValues>(BorderValues.Single), 
      Size = 12 },
    new RightBorder { 
      Val = new EnumValue<BorderValues>(BorderValues.Single), 
      Size = 12 },
    new InsideHorizontalBorder { 
      Val = new Value<BorderValues>(BorderValues.Single), 
      Size = 12 },
    new InsideVerticalBorder { 
      Val = new EnumValue<BorderValues>(BorderValues.Single), 
      Size = 12 }));
table.AppendChild<TableProperties>(props);

The constructor for the TableProperties class lets you specify as many children as you want (similar to the constructor for the XElement class) and in this case, the code creates TopBorder, BottomBorder, LeftBorder, RightBorder, InsideHorizontalBorder, and InsiderVerticalBorder child elements, each describing one of the border elements for the table. In each case, the code sets the Val and Size properties as part of calling the constructor. Setting the size is simple, but setting the Val property requires more effort: this property, for this particular object, represents the border style, and you must set it to an enumerated value. To do that, create an instance of the EnumValue generic type, passing the specific border type (BorderValues.Single) as a parameter to the constructor. Once the code has set all the table border value it must set, it calls the AppendChild method of the table, which indicates that the generic type is TableProperties—that is, it is appending an instance of the TableProperties class by using the variable props as the value.

Filling the Table with Data

Given that table and its properties, now fill the table with data. The sample procedure iterates first through all the rows of data in the array of strings that you specified, creating a new TableRow instance for each row of data. The following code leaves out the details of filling in the row with data. However, it shows how you create and append the row to the table.

For i = 0 To UBound(data, 1)
  Dim tr As New TableRow
  ' Code removed here…
  table.Append(tr)
Next
for (var i = 0; i <= data.GetUpperBound(0); i++)
{
  var tr = new TableRow();
  // Code removed here…
  table.Append(tr);
}

For each row, the code iterates through all the columns in the array of strings that you specified. For each column, the code creates a new TableCell, fills it with data, and appends it to the row. The following code leaves out the details of filling each cell with data. However, it shows how you create and append the column to the table.

For j = 0 To UBound(data, 2)
  Dim tc As New TableCell
  ' Code removed here…
  tr.Append(tc)
Next
for (var j = 0; j <= data.GetUpperBound(1); j++)
{
  var tc = new TableCell();
  // Code removed here…
  tr.Append(tc);
}

Next, the code create a new Text object that contains a value from the array of strings, passes that object to the constructor for a new Run object, passes that object to the constructor for a new Paragraph object, and passes that object to the Append method of the cell. In other words, the code appends the text to the new TableCell object.

tc.Append(new Paragraph(new Run(new Text(data[i, j]))));

The code then appends a new TableCellProperties object to the cell. This TableCellProperties object, such as the TableProperties object that you already saw, can accept as many objects in its constructor as you care to supply. In this case, the code passes only a new TableCellWidth object, with its Type property set to TableWidthUnitValues.Auto (so that the table automatically sizes the width of each column).

' Assume you want columns that are automatically sized.
tc.Append(New TableCellProperties(
  New TableCellWidth With {.Type = TableWidthUnitValues.Auto}))
// Assume you want columns that are automatically sized.
tc.Append(new TableCellProperties(
  new TableCellWidth { Type = TableWidthUnitValues.Auto }));

Finishing Up

The code concludes by appending the table to the body of the document and then saving the document.

doc.Body.Append(table)
doc.Save()
doc.Body.Append(table);
doc.Save();

Sample Procedure

The following code example contains the complete sample procedure.

Public Sub WDAddTable(ByVal fileName As String,
                      ByVal data(,) As String)
  Using document = WordprocessingDocument.Open(fileName, True)

    Dim doc = document.MainDocumentPart.Document

    Dim table As New Table()

    Dim props As TableProperties = _
      New TableProperties(New TableBorders( _
      New TopBorder With {
        .Val = New EnumValue(Of BorderValues)(BorderValues.Single),
        .Size = 12},
      New BottomBorder With {
        .Val = New EnumValue(Of BorderValues)(BorderValues.Single),
        .Size = 12},
      New LeftBorder With {
        .Val = New EnumValue(Of BorderValues)(BorderValues.Single),
        .Size = 12},
      New RightBorder With {
        .Val = New EnumValue(Of BorderValues)(BorderValues.Single),
        .Size = 12}, _
      New InsideHorizontalBorder With {
        .Val = New EnumValue(Of BorderValues)(BorderValues.Single),
        .Size = 12}, _
      New InsideVerticalBorder With {
        .Val = New EnumValue(Of BorderValues)(BorderValues.Single),
        .Size = 12}))
    table.AppendChild(Of TableProperties)(props)

    For i = 0 To UBound(data, 1)
      Dim tr As New TableRow
      For j = 0 To UBound(data, 2)
        Dim tc As New TableCell
        tc.Append(New Paragraph(New Run(New Text(data(i, j)))))
        ' Assume you want columns that are automatically sized.
        tc.Append(New TableCellProperties(
          New TableCellWidth With {.Type = TableWidthUnitValues.Auto}))
        tr.Append(tc)
      Next
      table.Append(tr)
    Next
    doc.Body.Append(table)
    doc.Save()
  End Using
End Sub
public static void WDAddTable(string fileName, string[,] data)
{
  using (var document = WordprocessingDocument.Open(fileName, true))
  {

    var doc = document.MainDocumentPart.Document;

    Table table = new Table();

    TableProperties props = new TableProperties(
      new TableBorders(
        new TopBorder
        {
          Val = new EnumValue<BorderValues>(BorderValues.Single),
          Size = 12
        },
        new BottomBorder
        {
          Val = new EnumValue<BorderValues>(BorderValues.Single),
          Size = 12
        },
        new LeftBorder
        {
          Val = new EnumValue<BorderValues>(BorderValues.Single),
          Size = 12
        },
        new RightBorder
        {
          Val = new EnumValue<BorderValues>(BorderValues.Single),
          Size = 12
        },
        new InsideHorizontalBorder
        {
          Val = new EnumValue<BorderValues>(BorderValues.Single),
          Size = 12
        },
        new InsideVerticalBorder
        {
          Val = new EnumValue<BorderValues>(BorderValues.Single),
          Size = 12
        }));
    table.AppendChild<TableProperties>(props);

    for (var i = 0; i <= data.GetUpperBound(0); i++)
    {
      var tr = new TableRow();
      for (var j = 0; j <= data.GetUpperBound(1); j++)
      {
        var tc = new TableCell();
        tc.Append(new Paragraph(new Run(new Text(data[i, j]))));
        // Assume you want columns that are automatically sized.
        tc.Append(new TableCellProperties(
          new TableCellWidth { Type = TableWidthUnitValues.Auto }));
        tr.Append(tc);
      }
      table.Append(tr);
    }
    doc.Body.Append(table);
    doc.Save();
  }
}
Read It

The sample that is included with this Visual How To describes code that inserts a table in a Word 2007 or Word 2010 document. To use the sample, you must install the Open XML SDK 2.0, available from the link listed in the Explore It section. The sample also uses code included as part of a set of code examples for the Open XML SDK 2.0. The Explore It section also includes a link to the full set of code examples, although you can use the sample without downloading and installing the code examples.

The sample application shows only a few of the available properties provided by the Open XML SDK 2.0 that you can interact with when you are creating Word tables. For more information, see the documentation that is included with the Open XML SDK 2.0 Productivity Tool: Click the Open XML SDK Documentation tab in the lower-left corner of the application window, and search for the class that you want to study. Start by examining the TableProperties and TableCellProperties classes. Although the documentation does not currently include code examples, given the sample shown here and the documentation, you should be able to successfully modify the sample application.

See It

Watch the video

> [!VIDEO https://www.microsoft.com/en-us/videoplayer/embed/c3fb4670-1bea-453f-9624-a95d8ac2e0e5]

Length: 00:20:29

Click to grab code

Grab the Code

Explore It

About the Author
Ken Getz is a senior consultant with MCW Technologies. He is coauthor of ASP.NET Developers Jumpstart (Addison-Wesley, 2002), Access Developer's Handbook (Sybex, 2001), and VBA Developer's Handbook, 2nd Edition (Sybex, 2001).