Imme Pak
Imme Pak

Reputation: 160

OpenXML sdk 2.5 Excel new column issue

I have part of code that generates Excel document using OpenXML. The problem is to set custom column width. This question is frequently discussed herew on SO, but unfortunately nothing helped to me.

So here the code of creating file:

SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Create(stream
     , SpreadsheetDocumentType.Workbook);
WorkbookPart workbookpart = spreadsheetDocument.AddWorkbookPart();
workbookpart.Workbook = new Workbook();
WorksheetPart worksheetPart = workbookpart.AddNewPart<WorksheetPart>();
worksheetPart.Worksheet = new Worksheet(new SheetData());
Sheets sheets = spreadsheetDocument.WorkbookPart.Workbook.
AppendChild<Sheets>(new Sheets());
Sheet sheet = new Sheet()
{
     Id = spreadsheetDocument.WorkbookPart.
     GetIdOfPart(worksheetPart),
     SheetId = 1,
     Name = _sheetName
};
sheets.Append(sheet);
document = spreadsheetDocument;
wbPart = workbookpart

After creating I am trying to set custom column width to the first column

Worksheet ws = ((WorksheetPart)(wbPart.GetPartById(sheet.Id))).Worksheet;
Columns columns = new Columns();                
Column column = new Column() { Min = (UInt32Value)5U, Max = (UInt32Value)5U,
     Width = 16D, CustomWidth = true };
columns.Append(column);
ws.Append(columns);
ws.Save();

Code runs without any exceptions, but result file is broken Here is the structure opf result sheet xml

<?xml version="1.0" encoding="UTF-8"?>
-<x:worksheet xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
-<x:sheetData> 
      -<x:row r="7"> 
         -<x:c r="A7" t="s" s="6">    
              <x:v>11</x:v>   
          </x:c> 
         -<x:c r="B7" t="s" s="6">    
              <x:v>12</x:v>    
          </x:c>  
         -<x:c r="C7" t="s" s="6">    
              <x:v>13</x:v>    
          </x:c>    
     </x:row>    
</x:sheetData>
-<x:cols>    
     <x:col customWidth="1" width="16" max="5" min="5"/>    
</x:cols>    
</x:worksheet>

So the question is, what am I doing wrong ?

UPD. Problem solved, thanks to petelids. I just added :

SheetData sheetData = ws.GetFirstChild<SheetData>();
ws.InsertBefore(columns,sheetData);

And then, only specify the range here Min = (UInt32Value)5U, Max = (UInt32Value)5U

Upvotes: 1

Views: 641

Answers (1)

petelids
petelids

Reputation: 12815

You have the order of your elements incorrect which leads to a corrupted file message. The ECMA-376 standard defines the XML for a Worksheet as

<xsd:complexType name="CT_Worksheet">
  <xsd:sequence>
    <xsd:element name="sheetPr" type="CT_SheetPr" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="dimension" type="CT_SheetDimension" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="sheetViews" type="CT_SheetViews" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="sheetFormatPr" type="CT_SheetFormatPr" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="cols" type="CT_Cols" minOccurs="0" maxOccurs="unbounded"/>
    <xsd:element name="sheetData" type="CT_SheetData" minOccurs="1" maxOccurs="1"/>
    <xsd:element name="sheetCalcPr" type="CT_SheetCalcPr" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="sheetProtection" type="CT_SheetProtection" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="protectedRanges" type="CT_ProtectedRanges" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="scenarios" type="CT_Scenarios" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="autoFilter" type="CT_AutoFilter" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="sortState" type="CT_SortState" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="dataConsolidate" type="CT_DataConsolidate" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="customSheetViews" type="CT_CustomSheetViews" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="mergeCells" type="CT_MergeCells" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="phoneticPr" type="CT_PhoneticPr" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="conditionalFormatting" type="CT_ConditionalFormatting" minOccurs="0" maxOccurs="unbounded"/>
    <xsd:element name="dataValidations" type="CT_DataValidations" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="hyperlinks" type="CT_Hyperlinks" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="printOptions" type="CT_PrintOptions" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="pageMargins" type="CT_PageMargins" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="pageSetup" type="CT_PageSetup" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="headerFooter" type="CT_HeaderFooter" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="rowBreaks" type="CT_PageBreak" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="colBreaks" type="CT_PageBreak" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="customProperties" type="CT_CustomProperties" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="cellWatches" type="CT_CellWatches" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="ignoredErrors" type="CT_IgnoredErrors" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="smartTags" type="CT_SmartTags" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="drawing" type="CT_Drawing" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="drawingHF" type="CT_DrawingHF" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="picture" type="CT_SheetBackgroundPicture" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="oleObjects" type="CT_OleObjects" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="controls" type="CT_Controls" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="webPublishItems" type="CT_WebPublishItems" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="tableParts" type="CT_TableParts" minOccurs="0" maxOccurs="1"/>
    <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
  </xsd:sequence>
</xsd:complexType>

Notice that it's a sequence so the order of the items matters and cols comes before sheetData (lines 5 and 6).

In your case you need to add the Columns directly before SheetData. There's an InsertBefore method on the Worksheet which can be used in place of your call to Append.

Upvotes: 2

Related Questions