views:

47

answers:

1

I need to retrieve Header/Footer parts from an OpenXML document in the order that they appear in the document.

The following:-

foreach (HeaderPart header in document.MainDocumentPart.HeaderParts)
{
  ...
}

-appears to iterate through the HeaderParts in no particular order.

Can anyone explain how to order these correctly? Either by using OrderBy, or by accessing the HeaderParts differently?

Edit: Examples

For example:-

In an example document I have several section breaks. Each section has a different header/footer:-

  • Section 1 => Section 1 Footer
  • Section 2 => Section 2 Footer
  • Section 3 => Section 3 Footer
  • Section 4 => Section 4 Footer

There are no "different first page" or "different odd/even" headers or footers in the document.

When I attempt to iterate over these footers using document.MainDocumentPart.FooterParts, they do not appear in the order 1, 2, 3, 4. I have not been able to determine the logic behind the order which these footers appear in the sequence. I suspect that they are not ordered.

I need them in order.

A: 

You don't actually want to get the header/footer parts first, you want to get them inside of document.xml in the order which they appear - and then access their parts. For this, you'll need something like Linq to query the main document. After that, you can get their relationship IDs and from there use packaging to get the actual part. But to start with, you'll need to get to the xelement, like so:

Imports System.Linq
Imports <xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"&gt;

Module Module1
    Sub Main()
        Dim doc As String = "C:\headers.docx"
        Dim wordDoc = WordprocessingDocument.Open(doc, False)
        Using wordDoc
            Dim mainPart = wordDoc.MainDocumentPart
            Dim docStream As System.IO.StreamReader = New IO.StreamReader(mainPart.GetStream)
            Dim xDoc As XElement = XElement.Load(docStream)
            Dim sectionHeaders = From e In xDoc...<w:sectPr> Select e.<w:headerReference>
        End Using
    End Sub

End Module

Sorry for the VB.NET - I don't know C#. But the concept is the same.

Otaku
It's definitely not an artefact of "foreach". The footers appear in the sequence in the wrong order to begin with.
Iain Galloway
do you mean they appear backwards? This reason for this in Open XML is because of the z-order of where objects should appear.
Otaku
No, they appear in an unpredictable order. Sometimes forwards, sometimes backwards, sometimes mixed.
Iain Galloway
I've changed the answer above.
Otaku
Still not right. I'll edit the question.
Iain Galloway
Updated once again.
Otaku
There we go. What we actually ended up doing was getting them from MainDocumentPart.Parts, ordering by the relationship id (tricky because the id is of the form "rIdXX"). I suspect that was the problem all along - that FooterParts is ordered using string ordering on the whole relationship id (so "rId11" comes before "rId9")
Iain Galloway
That's also a good way.
Otaku