Author: Vijayeta Tilak, Sonata Software Limited

This article describes how a footer or header can be programmatically added to a word document from a .NET application using the System.IO.Packaging API.

A WordprocessingML document may contain a part named footerX.xml, which holds the footer text and the page number. This part is included in the document by a footer reference tag that includes a relationship to the footer part from within the document.xml "start part" as shown here:

      <w:sectPr w:rsidR="00A352BA">

                    <w:pgSz w:w="12240" w:h="15840" />

                    <w:footerReference w:type="default" r:id="rId8" />

                    <w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440"                         w:header="720" w:footer="720" w:gutter="0" />

                    <w:cols w:space="720" />

                    <w:docGrid w:linePitch="360" />

  </w:sectPr>

The relationship ID must be unique within the document.

The footerX.xml part has a node that specifies the style to be used to format the footer:

<w:pStyle w:val="Footer" />

A content type for the footer must also be included in the package, as shown here:

<Override PartName="/word/footer1.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml" />

A part relationship must also be created, using the same relationship ID as was used in Document.xml:

<Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer" Target="/word/footer1.xml" Id="rId8" />

 

The UI would consist of a single text box accepting the footer text from the user, which would be included the document the user selects.

Programmatically, a footer file is created with the text the user had keyed in.

A part of code (from .NET Code Snippets for Open XML Developers) would then open the package and include the footer file, create Part Relationship.

 

public void WDAddHeaderFooter(string docName, XmlDocument Doc,bool h)

    {

            //  Given a document name, and a XML document

           

 const string documentRelationshipType="http://schemas.openxmlformats.org /officeDocument/2006/ relationships/officeDocument";

const string wordmlNamespace = "http://schemas.openxmlformats.org /wordprocessingml/2006/3/main";

           

const string relationshipNamespace ="http://schemas.openxmlformats.org /officeDocument/2006/relationships";

           

      PackagePart documentPart = null;

      Uri uriHeaderFooter;

      string headerfooterContentType;

      string relationshipType;

      string reference;

 

 

      package = Package.Open(docName, FileMode.Open, FileAccess.ReadWrite);

           

      //  Get the main document part (document.xml).

 

foreach (System.IO.Packaging.PackageRelationship relationship in package. GetRelationshipsByType(documentRelationshipType))

            {

Uri documentUri = PackUriHelper.ResolvePartUri(new Uri("/", UriKind.Relative), relationship.TargetUri);

                 documentPart = package.GetPart(documentUri);

                 //  There is only one document.

                 break;

            }

      if (h)

        {

          uriHeaderFooter = new Uri("/word/header2.xml", UriKind.Relative);

headerfooterContentType="application/vnd.openxmlformats-officedocument. wordprocessingml.header+xml";

relationshipType = "http://schemas.openxmlformats.org/ officeDocument/2006/relationships/header";

          reference = "w:headerReference";

        }

       else

        {

          uriHeaderFooter = new Uri("/word/footer2.xml", UriKind.Relative);

headerfooterContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml";

relationshipType = "http://schemas.openxmlformats.org/officeDocument/ 2006/relationships/footer";

          reference = "w:footerReference";

               

        }

 

 

      if (package.PartExists(uriHeaderFooter))

         {

            //  Although you could delete the relationship

            //  to the existing node, the next time you save

            //  the document after making changes, Word

            //  will take care of this for you.

            

            package.DeletePart(uriHeaderFooter);

          }

           //  Create the new footer part:

PackagePart headerfooterPart =package.CreatePart(uriHeaderFooter, headerfooterContentType);

 

 

           //  Write the footer out to its part.

           Doc.Save(headerfooterPart.GetStream());

 

           //  Create the document's relationship to the new part:

PackageRelationship rel = documentPart.CreateRelationship(uriHeaderFooter, TargetMode.Internal, relationshipType);

           string relID = rel.Id;

 

           //  Manage namespaces to perform Xml XPath queries.

           NameTable nt = new NameTable();

           XmlNamespaceManager nsManager = new XmlNamespaceManager(nt);

           nsManager.AddNamespace("w", wordmlNamespace);

 

           //  Get the document part from the package.

           //  Load the XML in the part into an XmlDocument instance:

           XmlDocument xdoc = new XmlDocument(nt);

           xdoc.Load(documentPart.GetStream());

 

           //  Find the node containing the document layout:

           XmlNode targetNode = xdoc.SelectSingleNode("//w:sectPr", nsManager);

           if (targetNode != null)

             {

                //  Delete any existing references to footers:

 

XmlNodeList headerfooterNodes = targetNode.SelectNodes("./"+reference, nsManager);

                    foreach (System.Xml.XmlNode headerfooterNode in headerfooterNodes)

                    {

                        targetNode.RemoveChild(headerfooterNode);

                    }

 

                    //  Create the new header reference node:

                    XmlElement node = xdoc.CreateElement(reference, wordmlNamespace);

 XmlAttribute attr=node.Attributes.Append(xdoc.CreateAttribute("r:id" ,relationshipNamespace));

                    attr.Value = relID;

                    node.Attributes.Append(attr);

                    targetNode.InsertBefore(node, targetNode.FirstChild);

              }

                //  Save the document XML back to its part.

                xdoc.Save(documentPart.GetStream(FileMode.Create, FileAccess.Write));

                package.Close();

      }