Search code examples
c#excelopenxml

Specific order of xmlelements in Excel OpenXml Workbook class


I create PowerPoint presentations via OpenXml. The slides of the presentations are enriched with embedded objects. Typically Excel documents are embedded. Beside having the image and the document prepared for embedding, Excel needs another information which area shall be shown to the user when the document is opened in PowerPoint.

This information can be added to the Excel workbook by adding OleSize class to the workbook part. Please ignore that this code doesn't check for existance of that fragment which would certainly lead to an issue. This is just a simple example.

    var oleSize = new OleSize() {Reference = "A1:H12"};
    var workbook = document.WorkbookPart.Workbook;
    workbook.Append(oleSize);

When just added to the end of the list of OpenXmlElements of the workbook class, Excel will show an error message dialog saying that the file is corrupt, it is not repairable. Putting this element directly after PivotCache OpenXmlElement does work as a workaround. Now I experienced that Excel also raises that message when the OpenXmlElement is available before OleSize.

I cannot find any information about the necessity of an order of OpenXmlElements for that specific class.

Any hint is highly appreciated.


Solution

  • You're right about the order you list in your answer. In the OpenXML Specification document that you refer to there is an XSD (page 3936) for the Workbook which shows that the order is indeed mandatory as it's defined as a Sequence:

    <xsd:complexType name="CT_Workbook">
        <xsd:sequence>
            <xsd:element name="fileVersion" type="CT_FileVersion" minOccurs="0" maxOccurs="1"/>
            <xsd:element name="fileSharing" type="CT_FileSharing" minOccurs="0" maxOccurs="1"/>
            <xsd:element name="workbookPr" type="CT_WorkbookPr" minOccurs="0" maxOccurs="1"/>
            <xsd:element name="workbookProtection" type="CT_WorkbookProtection" minOccurs="0" maxOccurs="1"/>
            <xsd:element name="bookViews" type="CT_BookViews" minOccurs="0" maxOccurs="1"/>
            <xsd:element name="sheets" type="CT_Sheets" minOccurs="1" maxOccurs="1"/>
            <xsd:element name="functionGroups" type="CT_FunctionGroups" minOccurs="0" maxOccurs="1"/>
            <xsd:element name="externalReferences" type="CT_ExternalReferences" minOccurs="0" maxOccurs="1"/>
            <xsd:element name="definedNames" type="CT_DefinedNames" minOccurs="0" maxOccurs="1"/>
            <xsd:element name="calcPr" type="CT_CalcPr" minOccurs="0" maxOccurs="1"/>
            <xsd:element name="oleSize" type="CT_OleSize" minOccurs="0" maxOccurs="1"/>
            <xsd:element name="customWorkbookViews" type="CT_CustomWorkbookViews" minOccurs="0" maxOccurs="1"/>
            <xsd:element name="pivotCaches" type="CT_PivotCaches" minOccurs="0" maxOccurs="1"/>
            <xsd:element name="smartTagPr" type="CT_SmartTagPr" minOccurs="0" maxOccurs="1"/>
            <xsd:element name="smartTagTypes" type="CT_SmartTagTypes" minOccurs="0" maxOccurs="1"/>
            <xsd:element name="webPublishing" type="CT_WebPublishing" minOccurs="4129 0" maxOccurs="1"/>
            <xsd:element name="fileRecoveryPr" type="CT_FileRecoveryPr" minOccurs="0" maxOccurs="unbounded"/>
            <xsd:element name="webPublishObjects" type="CT_WebPublishObjects" minOccurs="0" maxOccurs="1"/>
            <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
        </xsd:sequence>
        <xsd:attribute name="conformance" type="s:ST_ConformanceClass"/>
    </xsd:complexType>
    

    If you're interested, I have an answer here which shows one way of adding items into the correct place in the file.