Printer Friendly Version      Send     
Click to Rate and Give Feedback
Related Articles

John Papa tackles questions about calling services from Silverlight 2 applications.

John Papa

MSDN Magazine November 2008

...

Read more!

Our security experts present 10 vulnerable pieces of code. Your mission is to find the holes (a.k.a. bad security practices) in the code.

Michael Howard and Bryan Sullivan

MSDN Magazine November 2008

...

Read more!

Here we introduce Microsoft Code Name “Geneva,” the new framework for building claims-based applications and services, and federated security scenarios.

Michele Leroux Bustamante

MSDN Magazine December 2008

...

Read more!

This article presents an overview of the motivation behind new techniques that decompose problems into independent pieces for optimal use of parallel programming.

David Callahan

MSDN Magazine October 2008

...

Read more!

Matt Milner takes a look at some of the challenges and techniques related to testing Windows Workflow Foundation activities, workflows, and associated components.

Matt Milner

MSDN Magazine November 2008

...

Read more!

Also by this Author

At the beginning of another lovely day of writing courseware in mad pursuit of unrealistic deadlines, I received a frantic call from a business partner. He was at the end of a long consulting project and had several hundred Microsoft® Word documents, all of which required their document properties to be set identically, except the Title property of the document, which was to be based on the document file name, minus the .

Ken Getz

MSDN Magazine March ...

Read more!

If you're like me, you regularly do tech-support for family, friends, and neighbors. You can't go to a party without hearing the familiar refrain: "I've just got a quick question. " It's always something—their Internet connections get dropped, they've got a virus, they can't install some piece of hardware, or some file has gone missing.

Ken Getz

MSDN Magazine December 2005

...

Read more!

If you've been following Ted Pattison's excellent series of Basic Instincts columns on multithreading and asynchronous behavior, you should by now be an expert on handling the issues involved in working with multiple threads in Windows®-based apps.

Ken Getz

MSDN Magazine March 2005

...

Read more!

LINQ to XML and the Microsoft SDK for Open XML Formats simplify access to the parts of a 2007 Office system Open XML document when retrieving or modifying data, resulting in shorter, less complex code.

Ken Getz

MSDN Magazine March 2008

...

Read more!

Microsoft Visual Studio Tools for the Microsoft Office System is a new technology that brings the advanced features of Visual Studio .NET and the .NET Framework to applications built for Microsoft Office Word 2003 and Microsoft Office Excel 2003. Deploying solutions built with this technology requires that you understand how runtime security is enforced in managed applications and how to configure users' systems to run your solutions without introducing security holes.To promote that understanding, this article will demonstrate how to establish ...

Read more!

Popular Articles

Here we present techniques for programmatic and declarative data binding and display with Windows Presentation Foundation.

Josh Smith

MSDN Magazine July 2008

...

Read more!

This article presents an overview of the motivation behind new techniques that decompose problems into independent pieces for optimal use of parallel programming.

David Callahan

MSDN Magazine October 2008

...

Read more!

Jeff Prosise explains when it's better to use UpdatePanel and when it's better to use asynchronous calls to WebMethods or page methods instead.

Jeff Prosise

MSDN Magazine June 2007

...

Read more!

The MVP pattern helps you separate your logic and keep your UI layer free of clutter. This month learn how.

Jean-Paul Boodhoo

MSDN Magazine August 2006

...

Read more!

James Avery does it again with his popular list of developer tools. This time he covers the best Visual Studio add-ins available today that you can download for free.

James Avery

MSDN Magazine December 2005

...

Read more!

Our Blog

Because Windows Workflow Foundation (WF) is based on a runtime that manages the execution of workflows and activities, testing must, in almost all cases, involve the use of the runtime – and this can introduce some interesting challenges.

In the November 2008 issue of MSDN Magazine, Matt Milner presents some techniques for unit testing ...

Read more!

Windows Workflow Foundation (WF) imposes some restrictions on the developer authoring programs that target it. But in return WF offers a powerful, flexible, and extensible set of runtime services such as support for long-running code.

In the December 2008 issue of MSDN Magazine, Josh Lane provides some best practices to consider ...

Read more!

Silverlight provides a browser interoperability layer that allows managed code to access the document object model (DOM) of the underlying page. At the same time, JavaScript code running in the page can access the XAML content of the plug-in and even make modifications.

In the November 2008 issue of MSDN Magazine, Dino Esposito discusses the ...

Read more!

Windows Presentation Foundation (WPF) adds functionality to the Microsoft .NET Framework so that you actually can reliably keep bound controls synchronized with their data sources.

In the December 2008 issue of MSDN Magazine, Ken Getz demonstrates how to use the ObservableCollection class provided by WPF to keep bound controls in ...

Read more!

We're currently in the process of stepping back and taking a critical look at our Web site to see how you all are using it - and how we can redesign parts of it (big or small) to make that experience better.  We are continuously receiving your feedback on existing frustrations and we are working hard to remedy those (as a general fyi, most of the frustrations have to do with navigation).  However, in order to get a sense of whether we need to look at some of the more fundamental ...

Read more!

Advanced Basics
Setting Word Document Properties the Office 2007 Way
Ken Getz

Code download available at: AdvBasics2006_06.exe (167 KB)
Browse the Code Online
The last time I wrote this column (March 2006), I shared an application that allows you to update all the Microsoft® Word documents in a folder and its subfolders. Each time the application finds a document in the specified path, it updates the document properties to match those you specified in the application. I use this application myself. I often need to change a group of Word documents, setting all the properties to match, and performing this task by hand is a real chore. I'm revisiting this topic with a new version of the application. For information on the prior version, check out my previous column. That column explains the application and discusses its plumbing (which includes Windows® Forms data binding and automation of Microsoft Word 2003).
The original application has some shortcomings. It requires each document to be loaded into Microsoft Word, where the properties are manipulated and the document is saved, and then it moves on. Obviously, the application requires a copy of Word on the local computer. In addition, the application incurs the extra overhead of using COM interop to interact with Microsoft Word, and the inherent security issues involved in using unmanaged code as part of a managed application.
In the March column, I promised to revisit the issue. This time I've taken advantage of technology that is new to the Microsoft Office arena. I've rebuilt the application using the new Open XML file formats that are used by the upcoming release of 2007 Microsoft Office system (formerly code-named Office "12"). As you'll see, the new application allows you to modify the contents of Word documents without a copy of Word and without any COM interop involvement. There are also significant speed improvements. The new Open XML file format really makes manipulation fast and lightweight. Whereas the old application would read an entire Word document into memory, the new one simply loads the portion of the document necessary to make and save the changes. Figure 1 shows the finished Office 2007 version of the application.
Figure 1 Modify Core Document Properties 
Before getting started, I should point out that if you want to play with the sample associated with this column, you'll need to have Microsoft Office 2007 Beta 2 (or later) available so you can create documents using the new file format—this version of the sample won't work at all with files created in earlier versions of Microsoft Word, or with files using the old file format. In addition, you'll need a copy of Visual Studio® 2005. Finally, the classes that provide .NET Framework support for the Open XML file formats are only available starting with the latest builds of WinFX®, so you will also need at least the February 2006 community technology preview (CTP) version of WinFX.

Introducing the Open XML File Formats
In the past, each of the Microsoft Office products maintained data in its own proprietary format. I remember clearly, back in the late eighties, the pain involved in writing a file format converter to convert files from the word-processing product I was working on as a developer into a very early version of Microsoft Word. Each of the other applications, as well, was written to store its data in a proprietary format. These formats allowed each app to optimize its serialization/deserialization techniques specifically for its particular file format. But the closed nature of the formats made it difficult for "outsiders" to work with the data natively. You could use COM Automation to load a copy of the product, load the document, and then programmatically modify the document as necessary. This sort of work is clumsy and slow, and taking on this task in a server situation was nearly impossible due to licensing and threading limitations.
But this is a problem of the past now that Microsoft has opened up the Office file formats in Office 2007. Word 2007, Excel® 2007, and PowerPoint® 2007 lead this initiative, and other Office applications may follow suit in future versions. Each of these products saves its data natively in an XML-based format, making it reasonably easy for your applications to interact with these files, using tools provided by just about any programming language. Microsoft is even submitting the new file formats as a European Computer Manufacturers Association (ECMA) standard. But that's a story for a different article. For more information on the new file formats, visit the Microsoft Office Developer Center, and check out the overview.
The new file formats require a new file extension. If you work with Office 2007, you'll find *.docx, *.xlsx, and *.pptx files. And if you add VBA code to your documents, you'll find *.docm, *.xlsm, and *.pptm files. Templates and other files have their own new extensions, as well, but in reality, all these files are document parts that are grouped and saved in a standard ZIP file format. (By the official release of the upcoming version of Microsoft Office, you'll be able to download converters that enable Microsoft Office 2003 products to convert files from the new format, as well).
The sidebar "Get Inside a Word File" shows you how to manually look at and modify the various elements of a Word 2007 file (you needn't take any of the steps described in the sidebar if you're manipulating the files programmatically). As you can see, there is a lot more involved than you'd like to have to do in order to modify a document. However, WinFX provides support for opening the compressed Open XML file as a System.IO.Packaging.Package object, allowing you to programmatically investigate the relations and parts within the package. That's exactly how the sample for this column works.
The concept behind the Open XML file format is discoverability. You should be able to programmatically dive into a file and find the "start" part (the document itself) and all the subsidiary information. Simply put, everything is out in the open. All the information you need about the document is stored in XML content inside the Open XML file.

Investigating the Sample Project
If you compare the form shown in Figure 1 to the sample shown in my March 2006 column, you'll see that the new version contains slightly fewer properties. The difference is that in Office 2007, the document properties have been split into multiple parts: app.xml, core.xml, and custom.xml. In an attempt to concentrate on the technology, as opposed to fixating on functionality, I am going to focus only on the properties stored in core.xml. These include Title, Creator, Subject, Keywords, Comments, and a few others. You can easily modify the code you'll find here to work with other properties and other document parts. (Note that in order to work with the sample form within Visual Studio 2005, you may find it necessary to first open the Data Sources window.)
To give the application a try, create a group of Word 2007 documents, and store them in a folder, possibly with subfolders. Run the sample application in Visual Studio 2005 and select the root folder for the documents. If you want to recurse into subfolders, check the Include Subfolders checkbox. Click Make Changes when you're ready to roll and stand back. The application walks through all the files it finds, doing its work in a background thread and reporting on its progress in the status bar. The form saves and restores settings, including all your choices within the form (See the previous article for information on the behavior of the form—that's not the point of this article.)
In order to work with the Open XML file formats in your own projects, you'll need to have WinFX installed on the computer (the sample requires at least the February 2006 CTP version I mentioned earlier) and you'll need to set a reference to the appropriate assembly within WinFX. When I wrote this sample, this step required adding a reference within Visual Studio 2005 by browsing to the C:\Program Files\Reference Assemblies\Microsoft\WinFx\v3.0 folder and selecting the WindowsBase.dll assembly. This assembly contains the classes from the System.IO.Packaging namespace that are required in order to manipulate the files.
From here, the sample boils down to investigating the code. Besides handling the parts and the relations between the parts, most of the code you'll find in this application (and in any application that manipulates Office 2007 files) centers around XML handling. In this case, the application's goal is to find the docProps/core.xml part, make the necessary modifications, and then save the part.
If you open the sample project and load the form's code into the code editor, you'll see that most of the code in the top half of the form's class hasn't changed since the previous version. All the code that deals with the form's properties, saving user settings, and running a background thread is identical to the previous sample. Near the top of the file, however, you'll find the first major change, which involves System.IO.Packaging:
Imports System.IO.Packaging
The System.IO.Packaging namespace makes it possible to work with the compressed Open XML file formats, taking advantage of classes within the namespace. Applications that work with Open XML files need to interact with the relations between parts—a large part of the functionality that the System.IO.Packaging namespace provides—and this application is no exception. You shouldn't count on any particular folder layout for Open XML files: you should always use the relationships described in the file to find the part you need. This application is interested solely in the docProps/core.xml part, so it doesn't need to investigate or create relations.
Near the middle of the file, you'll find a comment indicating that the remaining code is specific to Office 2007. Immediately below the comment, you'll find three constants and three class-level variables, as shown here:
Private Const corePropertiesSchema As String = _
    "http://schemas.openxmlformats.org/" & _
    "package/2006/metadata/core-properties"
Private Const dcPropertiesSchema As String = _
    "http://purl.org/dc/elements/1.1/"
Private Const corePropertiesRelationshipType As String = _
    "http://schemas.openxmlformats.org/" & _
    "package/2006/relationships/metadata/core-properties"

Private wdPackage As Package
Private corePropertiesPart As PackagePart
Private nsManager As XmlNamespaceManager
The constants provide information about the namespaces used by core.xml, and the relationship type you'll use to find core.xml. When searching for elements later on, using the XmlDocument class's SelectSingleNode method, you'll need this namespace information. The variable of type System.IO.Packaging.Package, wdPackage, maintains a reference to the entire package (that is, the .docx file). The System.IO.Packaging.PackagePart variable, corePropertiesPart, refers to the actual core.xml part, while the variable of type System.Xml.XmlNamespaceManager, nsManager, maintains the System.Xml.NameTable object containing information about prefixes and namespaces for the XML manipulation.
The GetWordCorePropertyPart procedure retrieves the core.xml part and stores its XML content in a System.Xml.XmlDocument object for later manipulation (see Figure 2).
Private Function GetWordCorePropertyPart( _
        ByVal docName As String) As XmlDocument

    wdPackage = Package.Open( _
         docName, FileMode.Open, FileAccess.ReadWrite)
    ' Get the main document part (document.xml).

    ' Use the package relations to find the core
    ' properties part. There’s only one of these,
    ' so you can exit the loop immediately upon
    ' finding the part:
    For Each relation As PackageRelationship In _
      wdPackage.GetRelationshipsByType(corePropertiesRelationshipType)
        Dim corePropertiesUri As Uri = _
            PackUriHelper.ResolvePartUri( _
                New Uri("/", UriKind.Relative), relation.TargetUri)
        corePropertiesPart = wdPackage.GetPart(corePropertiesUri)
        ' There’s only one of these, so get out now.
        Exit For
    Next

    ' Manage namespaces to perform Xml XPath queries.
    Dim nt As New NameTable()
    nsManager = New XmlNamespaceManager(nt)
    nsManager.AddNamespace("cp", corePropertiesSchema)
    nsManager.AddNamespace("dc", dcPropertiesSchema)

    ' Get the properties from the package.
    ' Load the XML in the part into an XmlDocument instance:
    Dim xDoc As New XmlDocument(nt)
    Using partStream As Stream = corePropertiesPart.GetStream()
        xDoc.Load(partStream)
    End Using
    Return xDoc
End Function

The code starts by opening the package, with read/write access. The System.IO.Packaging.Package WinFX class provides the necessary Open method:
wdPackage = Package.Open( _
  docName, FileMode.Open, FileAccess.ReadWrite)
Get Inside a Word File
Figure A Extracting the Group Files 
Take a moment to investigate the various folders. The_rels folder contains a file named .rels, which contains XML information that defines the contents of the entire document. The information in the .rels file looks like the code in Figure B.


Figure B 
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <Relationships xmlns="http://schemas.openxmlformats.org/ package/2006/relationships"> <Relationship Id="rId3" Type="http://schemas.openxmlformats.org/ officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/> <Relationship Id="rId2" Type="http://schemas.openxmlformats.org/ package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/> <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/ officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/> <Relationship Id="rId4" Type="http://schemas.openxmlformats.org/ officeDocument/2006/relationships/custom-properties" Target="docProps/custom.xml"/> </Relationships>

The Target attribute in the file’s XML content provides references to the three main parts of the Word file: the application-specific properties, the core Office properties, and the document itself. It’s the docProps/core.xml part that the sample in this article manipulates.
When you look in the docProps and word folders, you’ll see that each contains various parts of the document (yes, the pieces that make up the document are really called "parts"). The docProps folder contains the XML files mentioned in the .rels file; the word folder contains the document, a folder (named rels) that contains another file (document.xml.rels) that lists the relations between the document and all its subsidiary pieces, a styles folder, and all the subsidiary parts (comments, settings, styles, and more).
Go to the docProps folder and open core.xml in a text editor. You’ll find XML that looks something like the code shown in Figure C. Modify one of the elements in this file, and then save the XML document.


Figure C 
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/ package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:dcmitype="http://purl.org/dc/dcmitype/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <dc:title>Doc title </dc:title> <dc:subject>MSDN Magazine: Fix Word Properties</dc:subject> <dc:creator>Ken Getz</dc:creator> <cp:keywords>Articles</cp:keywords> <dc:description>These are Peter’s comments.</dc:description> <cp:lastModifiedBy>Ken Getz</cp:lastModifiedBy> <cp:revision>4</cp:revision> <dcterms:created xsi:type="dcterms:W3CDTF"> 2005-12-21T22:18:00Z </dcterms:created> <dcterms:modified xsi:type="dcterms:W3CDTF"> 2006-03-29T16:45:00Z </dcterms:modified> <cp:category>Sample</cp:category> </cp:coreProperties>

You can easily modify the content of the Word document as well, simply by changing text within the XML file. To do this, browse to the word folder and open document.xml in a text editor. In the XML file, you’ll see a lot of XML content. Scroll down until you find the text you originally entered. Simply modify the text and save the XML file.
Close the document, browse to the root of the folder, right-click on the folder, and select Send To | Compressed (zipped) Folder from the context menu. Delete the folder that contained the decompressed file, and rename the newly created ZIP file to a file with the .docx extension.
When you open your document in Word, you’ll see the modifications you’ve just made. Check out the document properties, and you will see any changes you made there, as well.
A Word 2007 document is indeed the sum of its parts.

To retrieve a part from a package, you must ask the document to use its .rels part (which contains relation information for the document and properties parts) to retrieve the URI (Uniform Resource Identifier) of the core properties part. The code calls the GetRelationshipsByType method, which returns a collection of PackageRelationship objects. (There's no way to directly index into the relationships this method returns—you must iterate through the collection, although you can exit after the first item.) The relationship provides a TargetUri property, and the code uses the PackUriHelper class's ResolvePartUri method to retrieve a Uri object relative to the root of the document. Given this Uri, the code can get the core properties part:
For Each relation As PackageRelationship In _
        wdPackage.GetRelationshipsByType(corePropertiesRelationshipType)
    Dim corePropertiesUri As Uri = _
        PackUriHelper.ResolvePartUri( _
            New Uri("/", UriKind.Relative), relation.TargetUri)
    corePropertiesPart = wdPackage.GetPart(corePropertiesUri)
    ' There's only one of these, so get out now.
    Exit For
Next
Now that you've got the PackagePart in memory, you need to focus on its XML content. Because the application must search for items within the XML, it needs an XmlNamespaceManager to pass to the XmlDocument.SelectSingleNode method. The code creates the namespace manager, adds the two namespaces that the core.xml part uses, and creates a new XmlDocument instance using the System.Xml.NameTable instance associated with the namespace manager:
Dim nt As New NameTable()
nsManager = New XmlNamespaceManager(nt)
nsManager.AddNamespace("cp", corePropertiesSchema)
nsManager.AddNamespace("dc", dcPropertiesSchema)
Dim xDoc As New XmlDocument(nt)
Finally the code calls the PackagePart.GetStream method to load the contents of the part into memory, loading the XmlDocument with the contents of the stream. It then returns the new XmlDocument instance, as shown here:
Using partStream As Stream = corePropertiesPart.GetStream()
    xDoc.Load(partStream)
End Using
Return xDoc
Clicking the button on the form triggers the DoWork event of the BackgroundWorker component, and the DoWork event handler calls the HandleDocs method to search for and handle the documents, as shown in the following:
Private Sub bgw_DoWork( _
 ByVal sender As System.Object, _
 ByVal e As System.ComponentModel.DoWorkEventArgs) _
 Handles bgw.DoWork

    ' Handle the documents
    ' in the specified folder.
    Try
        HandleDocs(folderLabel.Text, e)
    Catch ex As Exception
        MessageBox.Show(ex.Message)
    End Try
End Sub
The HandleDocs procedure (covered in the March 2006 column) loops through folders, recursing into subfolders if requested. For each matching file the procedure finds, the OnFileFound procedure that you see in Figure 3 is called.
Private Sub OnFileFound(ByVal fi As FileInfo)
    Try
        bgw.ReportProgress(0, fi.Name)

        Dim xmlDoc As XmlDocument = _
            GetWordCorePropertyPart(fi.FullName)

        ' Title is a special case:
        If useTitleCheckbox.Checked Then
            Dim title As String
            If useDocNameCheckBox.Checked Then
                title = Path.GetFileNameWithoutExtension(fi.Name)
            Else
                title = titleTextBox.Text
            End If
            SetWordCoreProperty(xmlDoc, "dc:title", title)
        End If

        ' Handle all the rest of the properties:
        SetProperty(useSubjectCheckBox, xmlDoc, _
            "dc:subject", subjectTextBox)
        SetProperty(useAuthorCheckBox, xmlDoc, _
            "dc:creator", authorTextBox)
        SetProperty(useCategoryCheckBox, xmlDoc, _
            "cp:category", categoryTextBox)
        SetProperty(useKeywordsCheckBox, xmlDoc, _
            "cp:keywords", keywordsTextBox)
        SetProperty(useCommentsCheckBox, xmlDoc, _
            "dc:description", commentsTextBox)
        SaveWordCorePropertyPart(xmlDoc)

    Catch ex As Exception
        MessageBox.Show("Unable to change properties: " & _
            ex.Message)
    Finally
        If wdPackage IsNot Nothing Then wdPackage.Close()
    End Try
End Sub

After reporting progress (displaying the file name in the status bar within the BackgroundWorker component's ProgressChanged event handler) and loading the core properties part as shown in the previously discussed procedure, the code sets the various properties stored within the part. The code handles the Title property specially because it may use the document file name instead of the value you've supplied. Each property setting ends up calling the SetWordCoreProperty procedure, as shown in Figure 4.
Private Function SetWordCoreProperty( _
  ByVal xmlDoc As XmlDocument, ByVal propertyName As String, _
  ByVal propertyValue As String) As String
    ' Set the value of the specified property, within the XML
    '  document. Return the current value of the property.
    ' Note that property names are case-sensitive.

    Dim retval As String

    Dim searchString As String = _
      String.Format("//cp:coreProperties/{0}", propertyName)
    Dim xNode As XmlNode = xmlDoc.SelectSingleNode( searchString, nsManager)
    If xNode Is Nothing Then
        xNode = xmlDoc.CreateElement(propertyName, corePropertiesSchema)
        xNode.InnerText = propertyValue
        xmlDoc.DocumentElement.AppendChild(xNode)
        retval = String.Empty
    Else
        ' Get the current value:
        retval = xNode.InnerText
    End If
    If xNode IsNot Nothing Then
        ' Now update the value:
        xNode.InnerText = propertyValue
    End If
    Return retval
End Function
Investigating the SetWordCoreProperty procedure verifies that most of the work that you'll do with the Open XML file formats boils down to XML manipulation. This procedure sets up an XPath search string to look for an element with the property name, located beneath the cp:coreProperties element:
Dim searchString As String = _
  String.Format("//cp:coreProperties/{0}", propertyName)
Dim xNode As XmlNode = xmlDoc.SelectSingleNode( _
  searchString, nsManager)
Note that the XmlNamespaceManager instance maps the "cp" prefix used in this corresponding namespace within the part, and that you must supply the namespace prefix for each property you set. If the search turns up empty, the code creates the new node, using standard XmlDocument manipulations. If the search finds the node, it sets the variable that contains the procedure's return value to the current contents of the element:
If xNode Is Nothing Then
    xNode = xmlDoc.CreateElement(propertyName, _
      corePropertiesSchema)
    xNode.InnerText = propertyValue
    xmlDoc.DocumentElement.AppendChild(xNode)
    retval = String.Empty
Else
    ' Get the current value:
    retval = xNode.InnerText
End If
Finally, the procedure sets the inner text for the element and returns the original value:
If xNode IsNot Nothing Then
    ' Now update the value:
    xNode.InnerText = propertyValue
End If
Return retval
After modifying all the properties, the OnFileFound procedure calls the SaveWordCorePropertyPart procedure, which saves the XML document back to the core.xml property part:
Private Sub SaveWordCorePropertyPart( _
  ByVal xdoc As XmlDocument)
    ' Save the properties XML back to its part.
    Using infoStream As Stream = _
      corePropertiesPart.GetStream(FileMode.Create, _
      FileAccess.Write)
        xdoc.Save(infoStream)
    End Using
End Sub
Conveniently, the PackagePart class provides a GetStream method, which makes for an easy way to save the contents of the XML document back to the part.

Wrapping Up
That's all the Open XML code you'll need to accomplish the task for this particular case.
However, late in the process of writing this column, I discovered that the Package class provides a PackageProperties property that allows access to the exact properties the core.xml part provides. This means that for this particular scenario, you don't need to modify the XML. If you need to set or retrieve a particular core property, you can simply use the Package.PackageProperties property. On the other hand, because the point of this column is to demonstrate how you can manipulate the Office 2007 file formats directly, I left the code as is. Feel free to modify it to use PackageProperties instead. But keep in mind that if you need to work with document or custom properties you'll need to use code similar to the code presented in this column.
If you want to become proficient with the file formats, you'll need to read the documentation on the schemas for the various parts. And as Office 2007 matures, more information will be available on the MSDN Office developer site.
For more information on the Open XML file formats and all the Office gossip you could want, drop by Brian Jones's blog or Kevin Boske's blog.
I've spent a great deal of time over the past few months writing code samples using the new file formats. Although I will attest that it's easier to write VBA (Visual Basic for Applications) code to perform the same tasks, the flexibility provided by the Open XML file formats, combined with the fact that any vendor can now write applications that read and write Word, Excel, and PowerPoint files, makes the concept a winner. (Of course, you can still use VBA to program the content, just as you could in previous versions.)
Start digging into the file formats, investigating the schemas and the content of the various parts. You'll also need to beef up your XML programming skills. We're on the verge of a new way of interacting with Office files and the new formats open up entirely new avenues of interaction.

Send your questions and comments for Ken to  basics@microsoft.com.


Ken Getz is a senior consultant with MCW Technologies, and a courseware author for AppDev (www.appdev.com). He is coauthor of ASP .NET Developers Jumpstart (Addison-Wesley, 2002), Access Developer's Handbook (Sybex, 2002), and VBA Developer's Handbook, 2nd Edition (Sybex, 2001). Reach him at keng@mcwtech.com.

Page view tracker