Introduction
On April 2009, Microsoft published the Open XML Format SDK 2.0 CTP. Open XML is an open ECMA 376 standard, and is also approved as the ISO/IEC 29500 standard that defines a set of XML schemas for representing spreadsheets, charts, presentations, and word processing documents. Microsoft Office Word 2007, Excel 2007, and PowerPoint 2007 all use Open XML as the default file format. This SDK provides the functionality for easy creation, modification, and verification of Open XML files. In this article, I want to focus on the creation of Word 2007 (docx) documents using the Open XML Format SDK 2.0 CTP.
The Open XML Format SDK provides a simple API that allows to create and manipulate Open XML documents using one of the available languages from the .NET platform. Thanks to this SDK, a knowledge about XML and WordprocessingML is not required to work on Open XML documents (however, sometimes it is very useful). The SDK makes it easier for you to build solutions using the Open XML Format by allowing you to perform complex operations, such as creating Open XML Format packages (including easy support for internal documents, styles, themes, etc ...), or working with text and formatting like adding and deleting headers, paragraphs, tables, comments, etc…, with just a few lines of code.
First Application ("Hello World!" in Open XML)
Let’s start from an easy task: creation of a Word document that contains a sample and well known text: "Hello World!". For those who are familiar with WordprocessingML, we are going to crate a document with the following content:
="1.0"="utf-8"
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:body>
<w:p>
<w:r>
<w:t>Hello World!</w:t>
</w:r>
</w:p>
</w:body>
</w:document>
But the question is: how to do it in the Open XML Format SDK?
It is quite easy. At the beginning, it is required to add the following references to the project:
DocumentFormat.OpenXml
WindowsBase
The next step is adding the following namespaces (as using) to the code file:
DocumentFormat.OpenXml
DocumentFormat.OpenXml.Packaging
DocumentFormat.OpenXml.Wordprocessing
Now focus on the function that prepares the Word document containing "Hello World":
private void HelloWorld(string documentFileName)
{
using (WordprocessingDocument myDoc =
WordprocessingDocument.Create(documentFileName,
WordprocessingDocumentType.Document))
{
MainDocumentPart mainPart = myDoc.AddMainDocumentPart();
mainPart.Document = new Document();
Body body = new Body();
Paragraph paragraph = new Paragraph();
Run run_paragraph = new Run();
Text text_paragraph = new Text("Hello World!");
run_paragraph.Append(text_paragraph);
paragraph.Append(run_paragraph);
body.Append(paragraph);
mainPart.Document.Append(body);
mainPart.Document.Save();
}
}
The code above creates a Word Document file (according to the caller arguments), which contains a paragraph with the text: Hello World!”. Just like in the previously shown XML, the text is embedded inside the Run
element, that is embedded in Paragraph
, that is added to the body
and to the document
.
SaveFileDialog mySaveFileDialog=new SaveFileDialog();
mySaveFileDialog.Filter = "Word 2007 file (DOCX)|*.docx";
if (mySaveFileDialog.ShowDialog() == DialogResult.OK)
{
HelloWorld(mySaveFileDialog.FileName);
Process.Start(mySaveFileDialog.FileName);
}
Styles in Open XML SDK
In the previous section, we created a simple document. The font and style were default, but here comes the questions: How to change the font? How to change the size of the font? How to create a heading? The answer (for all of those questions) is styles (just like in Word), but how to do it in the SDK?
Let’s take a look at the example of creation of a document that will consist of two lines. The first line will be the heading of the paragraph (in this example, the font is red, bold, and the height is 28). The second one will be a standard paragraph. I have already described how to prepare an ordinary paragraph, so let’s focus on the first line (formatted according to our requirements).
The first task is the addition of the style definition part (StyleDefinitionsPart
) to the document. It should be added to the main document part:
WordprocessingDocument myDoc =
WordprocessingDocument.Create(documentFileName, WordprocessingDocumentType.Document)
MainDocumentPart mainPart = myDoc.AddMainDocumentPart();
StyleDefinitionsPart stylePart = mainPart.AddNewPart<StyleDefinitionsPart>();
Now, we have to define the font that we want to use (red, bold, and the height is 28):
RunProperties rPr = new RunProperties();
Color color = new Color() { Val = "FF0000" };
RunFonts rFont = new RunFonts();
rFont.Ascii = "Arial";
rPr.Append(color);
rPr.Append(rFont);
rPr.Append(new Bold());
rPr.Append(new FontSize() { Val = 28 });
Now, it is time for the style definition. Let’s call it "My Heading 1", the identifier is "MyHeading1
" (this identifier will be used directly in the Word document). The sample code below illustrates how to do it:
Style style = new Style();
style.StyleId = "MyHeading1";
style.Append(new Name() { Val = "My Heading 1" });
style.Append(new BasedOn() { Val = "Heading1" });
style.Append(new NextParagraphStyle() { Val = "Normal" });
style.Append(rPr);
After the creation of the style, we have to add this to the style document:
stylePart.Styles = new Styles();
stylePart.Styles.Append(style);
stylePart.Styles.Save();
The code above prepares the following style definition file in WordprocessingML:
="1.0"="utf-8"
<w:styles xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:style w:styleId="MyHeading1">
<w:name w:val="My Heading 1" />
<w:basedOn w:val="Heading1" />
<w:next w:val="Normal" />
<w:rPr>
<w:color w:val="FF0000" />
<w:rFonts w:ascii="Arial" />
<w:b />
<w:sz w:val="28" />
</w:rPr>
</w:style>
</w:styles>
We have finished the work that refers to the style creation; now, we have to assign the style to the selected paragraph. To do it, we will use the ParagraphProperties
class and its ParagraphStyleId
property:
Paragraph heading = new Paragraph();
Run heading_run = new Run();
Text heading_text = new Text("This is Heading");
ParagraphProperties heading_pPr = new ParagraphProperties();
heading_pPr.ParagraphStyleId = new ParagraphStyleId() { Val = "MyHeading1" };
heading.Append(heading_pPr);
heading_run.Append(heading_text);
heading.Append(heading_run);
The code above prepares the following document file in WordprocessingML:
="1.0"="utf-8"
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:body>
<w:p>
<w:pPr>
<w:pStyle w:val="MyHeading1" />
</w:pPr>
<w:r>
<w:t>This is Heading</w:t>
</w:r>
</w:p>
</w:body>
</w:document>
Tables in Open XML SDK
In this section, I want to focus on the creation of tables using the Open XML Format SDK. Thanks to the simple API, it is easy as the examples shown before. To create a table, we have to use the Table
class in which we embed the TableRow
and TableCell
elements. The simple example presents the code below:
Body body = new Body();
Table table = new Table(new TableRow(new TableCell(
new Paragraph(new Run(new Text("Hello World!"))))));
body.Append(table);
In the following example, I will show how to create a simple document that contains the "Multiplication table" (just like in school :) ):
Multiplication table
|
*
| 1
| 2
| 3
| 4
| 5
| 6
| 7
| 8
| 9
| 10
|
1
| 1
| 2
| 3
| 4
| 5
| 6
| 7
| 8
| 9
| 10
|
2
| 2
| 4
| 6
| 8
| 10
| 12
| 14
| 16
| 18
| 20
|
3
| 3
| 6
| 9
| 12
| 15
| 18
| 21
| 24
| 27
| 30
|
4
| 4
| 8
| 12
| 16
| 20
| 24
| 28
| 32
| 36
| 40
|
5
| 5
| 10
| 15
| 20
| 25
| 30
| 35
| 40
| 45
| 50
|
6
| 6
| 12
| 18
| 24
| 30
| 36
| 42
| 48
| 54
| 60
|
7
| 7
| 14
| 21
| 28
| 35
| 42
| 49
| 56
| 63
| 70
|
8
| 8
| 16
| 24
| 32
| 40
| 48
| 56
| 64
| 72
| 80
|
9
| 9
| 18
| 27
| 36
| 45
| 54
| 63
| 72
| 81
| 90
|
10
| 10
| 20
| 30
| 40
| 50
| 60
| 70
| 80
| 90
| 100
|
At the beginning of this section, there was an example that showed how to prepare the simplest table. Now, we will also use the Table
, TableCell
, and TableRow
elements, but additionally, we have to set the borders and span multiple columns in the first cell.
To set the borders, it is necessary to set special properties for the table. To do it, we have to use the TableProperties
and TableBorders
classes:
Table table = new Table();
TableProperties tblPr = new TableProperties();
TableBorders tblBorders = new TableBorders();
tblBorders.TopBorder = new TopBorder();
tblBorders.TopBorder.Val = new EnumValue<BorderValues>(BorderValues.Single);
tblBorders.BottomBorder = new BottomBorder();
tblBorders.BottomBorder.Val =new EnumValue<BorderValues>( BorderValues.Single);
tblBorders.LeftBorder = new LeftBorder();
tblBorders.LeftBorder.Val = new EnumValue<BorderValues>(BorderValues.Single);
tblBorders.RightBorder = new RightBorder();
tblBorders.RightBorder.Val = new EnumValue<BorderValues>(BorderValues.Single);
tblBorders.InsideHorizontalBorder = new InsideHorizontalBorder();
tblBorders.InsideHorizontalBorder.Val = BorderValues.Single;
tblBorders.InsideVerticalBorder = new InsideVerticalBorder();
tblBorders.InsideVerticalBorder.Val = BorderValues.Single;
tblPr.Append(tblBorders);
table.Append(tblPr);
Now, let’s take a look at the first row and its cell. We have to set the span attribute to span 11 columns. To do it, we have to set the special properties for this cell (TableCellProperties
) and its GridSpan
property.
tr = new TableRow();
tc = new TableCell(new Paragraph(new Run(new Text("Multiplication table"))));
TableCellProperties tcp=new TableCellProperties();
GridSpan gridSpan=new GridSpan();
gridSpan.Val=11;
tcp.Append(gridSpan);
tc.Append(tcp);
tr.Append(tc);
Finally, we have the following function:
public void HelloWorld_table(string docName)
{
using (WordprocessingDocument myDoc =
WordprocessingDocument.Create(docName,
WordprocessingDocumentType.Document))
{
MainDocumentPart mainPart = myDoc.AddMainDocumentPart();
mainPart.Document = new Document();
Body body = new Body();
Table table = new Table();
TableProperties tblPr = new TableProperties();
TableBorders tblBorders = new TableBorders();
tblBorders.TopBorder = new TopBorder();
tblBorders.TopBorder.Val = new EnumValue<bordervalues>(BorderValues.Single);
tblBorders.BottomBorder = new BottomBorder();
tblBorders.BottomBorder.Val =new EnumValue<bordervalues>( BorderValues.Single);
tblBorders.LeftBorder = new LeftBorder();
tblBorders.LeftBorder.Val = new EnumValue<bordervalues>(BorderValues.Single);
tblBorders.RightBorder = new RightBorder();
tblBorders.RightBorder.Val = new EnumValue<bordervalues>(BorderValues.Single);
tblBorders.InsideHorizontalBorder = new InsideHorizontalBorder();
tblBorders.InsideHorizontalBorder.Val = BorderValues.Single;
tblBorders.InsideVerticalBorder = new InsideVerticalBorder();
tblBorders.InsideVerticalBorder.Val = BorderValues.Single;
tblPr.Append(tblBorders);
table.Append(tblPr);
TableRow tr;
TableCell tc;
tr = new TableRow();
tc = new TableCell(new Paragraph(new Run(
new Text("Multiplication table"))));
TableCellProperties tcp=new TableCellProperties();
GridSpan gridSpan=new GridSpan();
gridSpan.Val=11;
tcp.Append(gridSpan);
tc.Append(tcp);
tr.Append(tc);
table.Append(tr);
tr = new TableRow();
tc = new TableCell();
tc.Append(new Paragraph(new Run(new Text("*"))));
tr.Append(tc);
for (int i = 1; i <= 10; i++)
{
tr.Append(new TableCell(new Paragraph(new Run(new Text(i.ToString())))));
}
table.Append(tr);
for (int i = 1; i <= 10; i++)
{
tr = new TableRow();
tr.Append(new TableCell(new Paragraph(new Run(new Text(i.ToString())))));
for (int j = 1; j <= 10; j++)
{
tr.Append(new TableCell(new Paragraph(new Run(new Text((i*j).ToString())))));
}
table.Append(tr);
}
body.Append(table);
mainPart.Document.Append(body);
mainPart.Document.Save();
}
}
The code above produces the following document file in WordprocessingML:
="1.0"="utf-8"
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:body>
<w:tbl>
<w:tblpr>
<w:tblborders>
<w:top w:val="single" />
<w:left w:val="single" />
<w:bottom w:val="single" />
<w:right w:val="single" />
<w:insideh w:val="single" />
<w:insidev w:val="single" />
</w:tblborders>
</w:tblpr>
<w:tr>
<w:tc>
<w:p>
<w:r>
<w:t>Multiplication table</w:t>
</w:r>
</w:p>
<w:tcpr>
<w:gridspan w:val="11" />
</w:tcpr>
</w:tc>
</w:tr>
<w:tr>
<w:tc>
<w:p>
<w:r>
<w:t>*</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:p>
<w:r>
<w:t>1</w:t>
</w:r>
</w:p>
</w:tc>
<!—- many cells and rows declarations -->
</w:tr>
</w:tbl>
</w:body>
</w:document>
Summary
I hope that this simple article will be useful for developers that are interested in development using the Open XML Format SDK. I am going to update this article in future to show more about this SDK and this format. The Polish version is available in parts at my blog.
History