Replace the theme part in a word processing document
This topic shows how to use the classes in the Open XML SDK for Office to programmatically replace a document part in a word processing document.
Packages and Document Parts
An Open XML document is stored as a package, whose format is defined by ISO/IEC 29500. The package can have multiple parts with relationships between them. The relationship between parts controls the category of the document. A document can be defined as a word-processing document if its package-relationship item contains a relationship to a main document part. If its package-relationship item contains a relationship to a presentation part it can be defined as a presentation document. If its package-relationship item contains a relationship to a workbook part, it is defined as a spreadsheet document. In this how-to topic, you will use a word-processing document package.
Getting a WordprocessingDocument Object
In the sample code, you start by opening the word processing file by
instantiating the WordprocessingDocument class as shown in
the following using
statement. In the same
statement, you open the word processing file document by using the
Open method, with the Boolean parameter set
to true
to enable editing the document.
using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(document, true))
With v3.0.0+ the Close() method
has been removed in favor of relying on the using statement.
It ensures that the Dispose() method 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. Because the WordprocessingDocument class in the Open XML SDK
automatically saves and closes the object as part of its IDisposable implementation, and because
Dispose() is automatically called when you
exit the block, you do not have to explicitly call Save() or
Dispose() as long as you use a using
statement.
How to Change Theme in a Word Package
If you would like to change the theme in a Word document, click the ribbon Design and then click Themes. The Themes pull-down menu opens. To choose one of the built-in themes and apply it to the Word document, click the theme icon. You can also use the option Browse for Themes... to locate and apply a theme file in your computer.
The Structure of the Theme Element
The theme element is constituted of color, font, and format schemes. In this how-to you learn how to change the theme programmatically. Therefore, it is useful to familiarize yourself with the theme element. The following information from the ISO/IEC 29500 specification can be useful when working with this element.
This element defines the root level complex type associated with a shared style sheet (or theme). This element holds all the different formatting options available to a document through a theme, and defines the overall look and feel of the document when themed objects are used within the document.
[Example: Consider the following image as an example of different themes in use applied to a presentation. In this example, you can see how a theme can affect font, colors, backgrounds, fills, and effects for different objects in a presentation. end example]
In this example, we see how a theme can affect font, colors, backgrounds, fills, and effects for different objects in a presentation. end example]
© ISO/IEC 29500: 2016
The following table lists the possible child types of the Theme class.
PresentationML Element | Open XML SDK Class | Description |
---|---|---|
<custClrLst/> |
CustomColorList | Custom Color List |
<extLst/> |
ExtensionList | Extension List |
<extraClrSchemeLst/> |
ExtraColorSchemeList | Extra Color Scheme List |
<objectDefaults/> |
ObjectDefaults | Object Defaults |
<themeElements/> |
ThemeElements | Theme Elements |
The following XML Schema fragment defines the four parts of the theme
element. The themeElements
element is the
piece that holds the main formatting defined within the theme. The other
parts provide overrides, defaults, and additions to the information
contained in themeElements
. The complex
type defining a theme, CT_OfficeStyleSheet
, is defined in the following
manner:
<complexType name="CT_OfficeStyleSheet">
<sequence>
<element name="themeElements" type="CT_BaseStyles" minOccurs="1" maxOccurs="1"/>
<element name="objectDefaults" type="CT_ObjectStyleDefaults" minOccurs="0" maxOccurs="1"/>
<element name="extraClrSchemeLst" type="CT_ColorSchemeList" minOccurs="0" maxOccurs="1"/>
<element name="custClrLst" type="CT_CustomColorList" minOccurs="0" maxOccurs="1"/>
<element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</sequence>
<attribute name="name" type="xsd:string" use="optional" default=""/>
</complexType>
This complex type also holds a CT_OfficeArtExtensionList
, which is used for
future extensibility of this complex type.
How the Sample Code Works
After opening the file, you can instantiate the MainDocumentPart
in the wordDoc
object, and
delete the old theme part.
using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(document, true))
{
if (wordDoc?.MainDocumentPart?.ThemePart is null)
{
throw new ArgumentNullException("MainDocumentPart and/or Body and/or ThemePart is null.");
}
MainDocumentPart mainPart = wordDoc.MainDocumentPart;
// Delete the old document part.
mainPart.DeletePart(mainPart.ThemePart);
You can then create add a new ThemePart
object and add it to the MainDocumentPart
object. Then you add content by using a StreamReader
and StreamWriter objects to copy the theme from the
themeFile
to the ThemePart object.
// Add a new document part and then add content.
ThemePart themePart = mainPart.AddNewPart<ThemePart>();
using (StreamReader streamReader = new StreamReader(themeFile))
using (StreamWriter streamWriter = new StreamWriter(themePart.GetStream(FileMode.Create)))
{
streamWriter.Write(streamReader.ReadToEnd());
}
Sample Code
The following code example shows how to replace the theme document part
in a word processing document with the theme part from another package.
The theme file passed as the second argument must be a valid theme part
in XML format (for example, Theme1.xml). You can extract this part from
an existing document or theme file (.THMX) that has been renamed to be a
.Zip file. To call the method ReplaceTheme
you can use the following call example to copy the theme from the file
from arg[1]
and to the file located at arg[0]
string document = args[0];
string themeFile = args[1];
ReplaceTheme(document, themeFile);
After you run the program open the Word file and notice the new theme changes.
Following is the complete sample code in both C# and Visual Basic.
// This method can be used to replace the theme part in a package.
static void ReplaceTheme(string document, string themeFile)
{
using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(document, true))
{
if (wordDoc?.MainDocumentPart?.ThemePart is null)
{
throw new ArgumentNullException("MainDocumentPart and/or Body and/or ThemePart is null.");
}
MainDocumentPart mainPart = wordDoc.MainDocumentPart;
// Delete the old document part.
mainPart.DeletePart(mainPart.ThemePart);
// Add a new document part and then add content.
ThemePart themePart = mainPart.AddNewPart<ThemePart>();
using (StreamReader streamReader = new StreamReader(themeFile))
using (StreamWriter streamWriter = new StreamWriter(themePart.GetStream(FileMode.Create)))
{
streamWriter.Write(streamReader.ReadToEnd());
}
}
}