Specific order of xmlelements in Excel OpenXml Workbook class

584 views Asked by At

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.

2

There are 2 answers

3
petelids On BEST ANSWER

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.

0
Holger Leichsenring On

After digging deep into OpenXml specification, 4th edition, I found this information:

sml_CT_Workbook =
     4261 attribute conformance { s_ST_ConformanceClass }?,
     4262 element fileVersion { sml_CT_FileVersion }?,
     4263 element fileSharing { sml_CT_FileSharing }?,
     4264 element workbookPr { sml_CT_WorkbookPr }?,
     4265 element workbookProtection { sml_CT_WorkbookProtection }?,
     4266 element bookViews { sml_CT_BookViews }?,
     4267 element sheets { sml_CT_Sheets },
     4268 element functionGroups { sml_CT_FunctionGroups }?,
     4269 element externalReferences { sml_CT_ExternalReferences }?,
     4270 element definedNames { sml_CT_DefinedNames }?,
     4271 element calcPr { sml_CT_CalcPr }?,
     4272 element oleSize { sml_CT_OleSize }?,
     4273 element customWorkbookViews { sml_CT_CustomWorkbookViews }?,
     4274 element pivotCaches { sml_CT_PivotCaches }?,
     4275 element smartTagPr { sml_CT_SmartTagPr }?,
     4276 element smartTagTypes { sml_CT_SmartTagTypes }?,
     4277 element webPublishing { sml_CT_WebPublishing }?,
     4278 element fileRecoveryPr { sml_CT_FileRecoveryPr }*,
     4279 element webPublishObjects { sml_CT_WebPublishObjects }?,
     4280 element extLst { sml_CT_ExtensionList }?

There is no information if this is the garantueed or expected order, but with just a few tests it looks promising (workbook openxml fragment from one of the test workbooks I checked for that order)

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<x:workbook xmlns:x15ac="http://schemas.microsoft.com/office/spreadsheetml/2010/11/ac" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:x15="http://schemas.microsoft.com/office/spreadsheetml/2010/11/main" mc:Ignorable="x15" xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
    <x:fileVersion appName="xl" lastEdited="6" lowestEdited="5" rupBuild="14420" />
    <x:workbookPr defaultThemeVersion="124226" />
    <mc:AlternateContent xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
        <mc:Choice Requires="x15">
            <x15ac:absPath xmlns:x15ac="http://schemas.microsoft.com/office/spreadsheetml/2010/11/ac" url="{path}" />
        </mc:Choice>
    </mc:AlternateContent>
    <x:bookViews>
        <x:workbookView xWindow="240" yWindow="90" windowWidth="23580"  windowHeight="10110" />
    </x:bookViews>
    <x:sheets>
        <x:sheet name="PRINT" sheetId="1" r:id="rId1" />
        <x:sheet name="PRINT2" sheetId="4" r:id="rId2" />
        <x:sheet name="Data" sheetId="5" state="veryHidden" r:id="rId3" />
        <x:sheet name="PRINT3" sheetId="6" r:id="rId4" />
    </x:sheets>
    <x:definedNames>
        <x:definedName name="Measures">Books!$C$4</x:definedName>
        <x:definedName name="_xlnm.Print_Area" localSheetId="0">PRINT!$A$1:$G$25</x:definedName>
    </x:definedNames>
    <x:calcPr calcId="152511" calcMode="manual" calcOnSave="0" />
    <x:oleSize ref="A1:G25" />
</x:workbook>

So I'll give the best guess a try.