Insert a table into a word processing document
This topic shows how to use the classes in the Open XML SDK for Office to programmatically insert a table into a word processing document.
Getting a WordprocessingDocument Object
To open an existing document, instantiate the WordprocessingDocument class as shown in the following using statement. In the same statement, open the word processing file at the specified filepath by using the Open method, with the Boolean parameter set to true in order to enable editing the document.
using (WordprocessingDocument doc =
WordprocessingDocument.Open(filepath, true))
{
// Insert other code here.
}
The using statement provides a recommended alternative to the typical .Create, .Save, .Close sequence. It ensures that the Dispose method (internal method used by the Open XML SDK to clean up resources) is automatically called when the closing brace is reached. The block that follows the using statement establishes a scope for the object that is created or named in the using statement, in this case doc. Because the WordprocessingDocument class in the Open XML SDK automatically saves and closes the object as part of its System.IDisposable implementation, and because Dispose is automatically called when you exit the block, you do not have to explicitly call Save and Close─as long as you use using.
Structure of a Table
The basic document structure of a WordProcessingML document consists of the document and body elements, followed by one or more block level elements such as p, which represents a paragraph. A paragraph contains one or more r elements. The r stands for run, which is a region of text with a common set of properties, such as formatting. A run contains one or more t elements. The t element contains a range of text.The document might contain a table as in this example. A table is a set of paragraphs (and other block-level content) arranged in rows and columns. Tables in WordprocessingML are defined via the tbl element, which is analogous to the HTML table tag. Consider an empty one-cell table (i.e. a table with one row, one column) and 1 point borders on all sides. This table is represented by the following WordprocessingML markup segment.
<w:tbl>
<w:tblPr>
<w:tblW w:w="5000" w:type="pct"/>
<w:tblBorders>
<w:top w:val="single" w:sz="4" w:space="0" w:color="auto"/>
<w:left w:val="single" w:sz="4 w:space="0" w:color="auto"/>
<w:bottom w:val="single" w:sz="4" w:space="0" w:color="auto"/>
<w:right w:val="single" w:sz="4" w:space="0" w:color="auto"/>
</w:tblBorders>
</w:tblPr>
<w:tblGrid>
<w:gridCol w:w="10296"/>
</w:tblGrid>
<w:tr>
<w:tc>
<w:tcPr>
<w:tcW w:w="0" w:type="auto"/>
</w:tcPr>
<w:p/>
</w:tc>
</w:tr>
</w:tbl>
This table specifies table-wide properties of 100% of page width using the tblW element, a set of table borders using the tblBorders element, the table grid, which defines a set of shared vertical edges within the table using the tblGrid element, and a single table row using the tr element.
How the Sample Code Works
In sample code, after you open the document in the using statement, you create a new Table object. Then you create a TableProperties object and specify its border information. The TableProperties class contains an overloaded constructor TableProperties() that takes a params array of type OpenXmlElement. The code uses this constructor to instantiate a TableProperties object with BorderType objects for each border, instantiating each BorderType and specifying its value using object initializers. After it has been instantiated, append the TableProperties object to the table.
// Create an empty table.
Table table = new Table();
// Create a TableProperties object and specify its border information.
TableProperties tblProp = new TableProperties(
new TableBorders(
new TopBorder() { Val = new EnumValue<BorderValues>(BorderValues.Dashed), Size = 24 },
new BottomBorder() { Val = new EnumValue<BorderValues>(BorderValues.Dashed), Size = 24 },
new LeftBorder() { Val = new EnumValue<BorderValues>(BorderValues.Dashed), Size = 24 },
new RightBorder() { Val = new EnumValue<BorderValues>(BorderValues.Dashed), Size = 24 },
new InsideHorizontalBorder() { Val = new EnumValue<BorderValues>(BorderValues.Dashed), Size = 24 },
new InsideVerticalBorder() { Val = new EnumValue<BorderValues>(BorderValues.Dashed), Size = 24 }
)
);
// Append the TableProperties object to the empty table.
table.AppendChild<TableProperties>(tblProp);
The code creates a table row. This section of the code makes extensive use of the overloaded Append[]) methods, which classes derived from OpenXmlElement inherit. The Append methods provide a way to either append a single element or to append a portion of an XML tree, to the end of the list of child elements under a given parent element. Next, the code creates a TableCell object, which represents an individual table cell, and specifies the width property of the table cell using a TableCellProperties object, and the cell content ("Hello, World!") using a Text object. In the Open XML Wordprocessing schema, a paragraph element (<p>) contains run elements (<r>) which, in turn, contain text elements (<t>). To insert text within a table cell using the API, you must create a Paragraph object that contains a Run object that contains a Text object that contains the text you want to insert in the cell. You then append the Paragraph object to the TableCell object. This creates the proper XML structure for inserting text into a cell. The TableCell is then appended to the TableRow object.
// Create a row.
TableRow tr = new TableRow();
// Create a cell.
TableCell tc1 = new TableCell();
// Specify the width property of the table cell.
tc1.Append(new TableCellProperties(new TableCellWidth() { Type = TableWidthUnitValues.Dxa, Width = "2400" }));
// Specify the table cell content.
tc1.Append(new Paragraph(new Run(new Text("Hello, World!"))));
// Append the table cell to the table row.
tr.Append(tc1);
The code then creates a second table cell. The final section of code creates another table cell using the overloaded TableCell constructor TableCell(String) that takes the OuterXml property of an existing TableCell object as its only argument. After creating the second table cell, the code appends the TableCell to the TableRow, appends the TableRow to the Table, and the Table to the Document object.
// Create a second table cell by copying the OuterXml value of the first table cell.
TableCell tc2 = new TableCell(tc1.OuterXml);
// Append the table cell to the table row.
tr.Append(tc2);
// Append the table row to the table.
table.Append(tr);
// Append the table to the document.
doc.MainDocumentPart.Document.Body.Append(table);
// Save changes to the MainDocumentPart.
doc.MainDocumentPart.Document.Save();
Sample Code
The following code example shows how to create a table, set its properties, insert text into a cell in the table, copy a cell, and then insert the table into a word processing document. You can invoke the method CreateTable by using the following call.
string fileName = @"C:\Users\Public\Documents\Word10.docx";
CreateTable(fileName);
After you run the program inspect the file "Word10.docx" to see the inserted table.
Following is the complete sample code in both C# and Visual Basic.
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using System;
CreateTable(args[0]);
// Insert a table into a word processing document.
static void CreateTable(string fileName)
{
// Use the file name and path passed in as an argument
// to open an existing Word 2007 document.
using (WordprocessingDocument doc
= WordprocessingDocument.Open(fileName, true))
{
// Create an empty table.
Table table = new Table();
// Create a TableProperties object and specify its border information.
TableProperties tblProp = new TableProperties(
new TableBorders(
new TopBorder()
{
Val =
new EnumValue<BorderValues>(BorderValues.Dashed),
Size = 24
},
new BottomBorder()
{
Val =
new EnumValue<BorderValues>(BorderValues.Dashed),
Size = 24
},
new LeftBorder()
{
Val =
new EnumValue<BorderValues>(BorderValues.Dashed),
Size = 24
},
new RightBorder()
{
Val =
new EnumValue<BorderValues>(BorderValues.Dashed),
Size = 24
},
new InsideHorizontalBorder()
{
Val =
new EnumValue<BorderValues>(BorderValues.Dashed),
Size = 24
},
new InsideVerticalBorder()
{
Val =
new EnumValue<BorderValues>(BorderValues.Dashed),
Size = 24
}
)
);
// Append the TableProperties object to the empty table.
table.AppendChild<TableProperties>(tblProp);
// Create a row.
TableRow tr = new TableRow();
// Create a cell.
TableCell tc1 = new TableCell();
// Specify the width property of the table cell.
tc1.Append(new TableCellProperties(
new TableCellWidth() { Type = TableWidthUnitValues.Dxa, Width = "2400" }));
// Specify the table cell content.
tc1.Append(new Paragraph(new Run(new Text("some text"))));
// Append the table cell to the table row.
tr.Append(tc1);
// Create a second table cell by copying the OuterXml value of the first table cell.
TableCell tc2 = new TableCell(tc1.OuterXml);
// Append the table cell to the table row.
tr.Append(tc2);
// Append the table row to the table.
table.Append(tr);
if (doc.MainDocumentPart is null || doc.MainDocumentPart.Document.Body is null)
{
throw new ArgumentNullException("MainDocumentPart and/or Body is null.");
}
// Append the table to the document.
doc.MainDocumentPart.Document.Body.Append(table);
}
}