Replacing the Styles Parts in 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 replace the styles in a Word document with an XDocument instance that contains the styles or stylesWithEffects part from a Microsoft Word document, without loading the document into Word.

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

Published:   February 2011

Provided by:   Ken Getz, MCW Technologies, LLC

Overview

The Open XML file formats make it possible to retrieve and modify blocks of content from Word documents, but doing so 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 retrieving and replacing, for example, an XDocument instance that contains the document styles or stylesWithEffects part. Given the XML content, you could archive the information, modify and reapply it, or apply it to a new document. The code sample included with this Visual How To shows how to the use the SDK to replace the styles or stylesWithEffects part, assuming that you know how to retrieve the part from an existing document. For more information about how to retrieve the styles or stylesWithEffects part from a Word document, see Extracting Styles from Word 2010 Documents by Using the Open XML SDK 2.0.

Code It

The sample provided with this Visual How To includes the code necessary to replace the styles or styleWithEffects part in a document, given an XDocument instance that contains the same part for a Word 2007 or Word 2010 document. The sample code includes the procedure that retrieves the part as an XDocument instance, as well, but this Visual How To assumes that you know how to do that The following sections describe the code in detail. Be aware that, for a document created in Word 2007, there will only be a single styles part; Word 2010 adds a second stylesWithEffects part. To provide for relaying a document from Word 2010 to Word 2007 and back, Word 2010 maintains both the original styles part and the new styles part. The Open XML specification requires that Microsoft Word disregard any parts that it does not recognize; Word 2007 does not recognize the stylesWithEffects part that Word 2010 adds to the document. This code example shows how to extract and replace both parts, although the code is effectively the same for both parts. The sample code replaces both style parts with the style information in the specified XDocument.

Setting Up References

To use the code from the Open XML SDK 2.0, you must add a few references to your project. The sample project already includes these references, but in your own code, you must 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.

Also, include the following using/Imports statements at the top of the code file.

Imports System.IO
Imports System.Xml
Imports DocumentFormat.OpenXml.Packaging
using System.IO;
using System.Xml;
using System.Xml.Linq;
using DocumentFormat.OpenXml.Packaging;

Examining the Procedure

The WDReplaceStyles procedure accepts three parameters: the first parameter contains a string that specifies the path to the file you want to modify. The second contains an XDocument that contains a reference to the style content from another Word document. The third indicates whether you want to replace the previous styles part, or the newer stylesWithEffects part (you must call this procedure twice for Word 2010 documents, replacing each of the parts with the corresponding parts from a source document).

Public Sub WDReplaceStyles(
  ByVal fileName As String, ByVal newStyles As XDocument,
  Optional ByVal setStylesWithEffectsPart As Boolean = True)
)
public static void WDReplaceStyles(
  string fileName, XDocument newStyles,
  bool setStylesWithEffectsPart = true)

The procedure examines the document you specify, looking for the styles with effects (or the previous styles) part. If the requested styles part exists, the procedure saves the supplied XDocument into the selected styles part. To call the procedure, pass the required parameter values, as shown in the example code. To use the sample code, provide documents named C:\temp\StylesFrom.docx and C:\temp\StylesTo.docx. The StylesFrom document should contain some specific style information (it may contain modified versions of the built-in styles Header 1, Header 2, and so on) which the example can copy into the StylesTo document. The sample relies on the WDExtractStyles procedure that is included in the sample code. This procedure also allows you to select whether you want to extra the stylesWithEffects part, or the older styles part.

Private Const fromDoc As String = "C:\Temp\StylesFrom.docx"
Private Const toDoc As String = "C:\Temp\StylesTo.docx"

Dim node = WDExtractStyles("C:\temp\StylesFrom.docx", True)
If node IsNot Nothing Then
  WDReplaceStyles("c:\temp\StylesTo.docx", node, True)
End If
const string fromDoc = @"C:\Temp\StylesFrom.docx";
const string toDoc = @"C:\Temp\StylesTo.docx";

var node = WDExtractStyles(@"C:\Temp\StylesFrom.docx", true);
if (node != null)
  WDReplaceStyles(@"C:\Temp\StylesTo.docx", node, true);

The sample code calls this same procedure twice; once for each of the styles parts. If you pass in a Word 2007 document that does not contain a stylesWithEffects part, the code drops out without attempting to extract or replace the part.

Accessing the Document

The code starts by opening the document, using the WordprocessingDocument.Open method and indicating that the document should be open for read/write access (the final true parameter). Given the open document, the code uses the MainDocumentPart property to navigate to the main document, and then prepares a variable named stylesPart to hold a reference to the styles part.

Using document = WordprocessingDocument.Open(fileName, True)
  Dim docPart = document.MainDocumentPart
  Dim stylesPart As StylesPart = Nothing
  ' Code removed here…
End Using
using (var document = WordprocessingDocument.Open(fileName, true))
{
  var docPart = document.MainDocumentPart;

  StylesPart stylesPart = null;
  // Code removed here…
}

Finding the Correct Styles Part

The code next retrieves a reference to the requested styles part, using the setStylesWithEffectsPart boolean parameter. Based on this value, the code retrieves a specific property of the docPart variable, and stores it in the stylesPart variable.

If setStylesWithEffectsPart Then
  stylesPart = docPart.StylesWithEffectsPart
Else
  stylesPart = docPart.StyleDefinitionsPart
End If
if (setStylesWithEffectsPart)
  stylesPart = docPart.StylesWithEffectsPart;
else
  stylesPart = docPart.StyleDefinitionsPart;

Saving the Part Contents

Assuming that the style part exists, the code must save the entire contents of the XDocument passed to the procedure to the style part. Each part provides a GetStream method, which returns a Stream. The code passes the Stream instance to the constructor of the StreamWriter class, creating a stream writer around the part stream. Finally, the code calls the Save method of the XDocument parameter, saving its contents into the styles part (this sequence of steps is quite common when working with XDocuments and Open XML parts─you will see it used often).

If stylesPart IsNot Nothing Then
  newStyles.Save(New StreamWriter(
    stylesPart.GetStream(FileMode.Create, FileAccess.Write)))
End If
If stylesPart IsNot Nothing Then
  Using reader = XmlNodeReader.Create(
    stylesPart.GetStream(FileMode.Open, FileAccess.Read))
    ' Create the XDocument:
    styles = XDocument.Load(reader)
  End Using
End If
if (stylesPart != null)
{
  newStyles.Save(new StreamWriter(stylesPart.GetStream(
    FileMode.Create, FileAccess.Write)));
}

Sample Procedure

The following code example contains the complete sample procedure.

Public Sub WDReplaceStyles(
  ByVal fileName As String, ByVal newStyles As XDocument,
  Optional ByVal setStylesWithEffectsPart As Boolean = True)

  Using document = WordprocessingDocument.Open(fileName, True)
    Dim docPart = document.MainDocumentPart

    Dim stylesPart As StylesPart = Nothing

    If setStylesWithEffectsPart Then
      stylesPart = docPart.StylesWithEffectsPart
    Else
      stylesPart = docPart.StyleDefinitionsPart
    End If
    If stylesPart IsNot Nothing Then
      newStyles.Save(New StreamWriter(
        stylesPart.GetStream(FileMode.Create, FileAccess.Write)))
    End If
  End Using
End Sub
public static void WDReplaceStyles(string fileName, 
  XDocument newStyles, 
  bool setStylesWithEffectsPart = true)
{
  using (var document = WordprocessingDocument.Open(fileName, true))
  {
    var docPart = document.MainDocumentPart;
 
    StylesPart stylesPart = null;
    if (setStylesWithEffectsPart)
      stylesPart = docPart.StylesWithEffectsPart;
    else
      stylesPart = docPart.StyleDefinitionsPart;
 
    if (stylesPart != null)
    {
      newStyles.Save(new StreamWriter(stylesPart.GetStream(
        FileMode.Create, FileAccess.Write)));
    }
  }
}
Read It

The sample included with this Visual How To demonstrates code that retrieves the two styles parts from a Word document and saves the information into the styles parts of a second document. To use the sample, install the Open XML SDK 2.0, available from the link listed in the Explore It section. The sample also uses a modified version of code included as part of a set of code snippets for the Open XML SDK 2.0. The Explore It section also includes a link to the full set of snippets, although you can use the sample without downloading and installing the snippets.

If you run the sample code in this Visual How To, starting with a source document that contains specific styles, you should find that those styles appear in the output document after running the code. This technique allows you to create a library of styles that you could apply to documents. Normally, you might use this technique to modify document templates, because if you are using Word styles, you most likely base your documents on particular templates that define their styles. Whether you apply the style to the template or to the document directly, using this technique allows you to modify the styles without needing to open the document in Microsoft Word.

The sample application demonstrates only a handful of the available properties and methods provided by the Open XML SDK 2.0 that you can interact with when modifying document structure. For more information, investigate the documentation 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 you need to study. Although the documentation does not always 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/951ee45d-afdf-4369-bf5d-56dcf724ec60]

Length: 00:10:43

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).