2016-09-21 2 views
1

Das ist, was ich tue:ein Datum in einer Excel-Zelle Hinzufügen mit OpenXML

CellFormat cellFormat = 
       new CellFormat() 
       { NumberFormatId = (UInt32Value)14U, 
        FontId = (UInt32Value)0U, 
        FillId = (UInt32Value)0U, 
        BorderId = (UInt32Value)0U, 
        FormatId = (UInt32Value)0U, 
        ApplyNumberFormat = true }; 

sd.WorkbookPart.WorkbookStylesPart.Stylesheet.CellFormats.AppendChild<CellFormat>(cellFormat); 

_dateStyleIndex = sd.WorkbookPart.WorkbookStylesPart.Stylesheet.CellFormats.Count() - 1; 

und dann irgendwo später in meinem Code

else if (type == DataTypes.DateTime) 
{     
    DateTime dateTime = DateTime.Parse(text); 
    double oaValue = dateTime.ToOADate(); 
    cell.CellValue = new CellValue(oaValue.ToString(CultureInfo.InvariantCulture)); 
    cell.DataType = new EnumValue<CellValues>(CellValues.Date); 
    cell.StyleIndex = Convert.ToUInt32(_dateStyleIndex);    
} 

Allerdings, wenn ich die erzeugte Excel-Validierung-Datei mit Open XML SDK Tool, bekomme ich den folgenden Validierungsfehler: Das Attribut 't' hat ungültigen Wert 'd'. Die Enumeration-Einschränkung ist fehlgeschlagen.

Was fehlt mir hier? Danke im Voraus für Ihre Hilfe.

PS: Hinzufügen, so sieht das x: sheetData aus. Es gibt mir die Validierungsfehler:

<x:sheetData xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main"> 
    <x:row r="2"> 
    <x:c r="B2" t="s"> 
     <x:v>0</x:v> 
    </x:c> 
    <x:c r="C2" t="s"> 
     <x:v>1</x:v> 
    </x:c> 
    <x:c r="D2" t="s"> 
     <x:v>2</x:v> 
    </x:c> 
    </x:row> 
    <x:row r="3"> 
    <x:c r="B3" t="s"> 
     <x:v>3</x:v> 
    </x:c> 
    <x:c r="C3" t="s"> 
     <x:v>6</x:v> 
    </x:c> 
    <x:c r="D3" s="1" t="d"> 
     <x:v>42634.906087963</x:v> 
    </x:c> 
    </x:row> 
    <x:row r="4"> 
    <x:c r="B4" t="s"> 
     <x:v>4</x:v> 
    </x:c> 
    <x:c r="C4" t="s"> 
     <x:v>7</x:v> 
    </x:c> 
    <x:c r="D4" s="1" t="d"> 
     <x:v>42634.9062037037</x:v> 
    </x:c> 
    </x:row> 
    <x:row r="5"> 
    <x:c r="B5" t="s"> 
     <x:v>5</x:v> 
    </x:c> 
    <x:c r="C5" t="s"> 
     <x:v>8</x:v> 
    </x:c> 
    <x:c r="D5" s="1" t="d"> 
     <x:v>42634.9062847222</x:v> 
    </x:c> 
    </x:row> 
</x:sheetData> 
+0

Setzen Sie nicht einfach cell.DataType auf CellValues.Date? Ich glaube nicht, dass Sie dafür einen EnumValue instanziieren. DataType hat ein Attribut von SchemaAttrAttribute, in dem ich annahm, dass es leer ist, was den Fehler verursacht. – Dispersia

+0

Und Sie haben nicht gesagt, welche Zeile es anwarf, aber wenn CellValue = ist, versuchen Sie, das DataType-Set davor zu verschieben. Vielleicht muss es seinen Typ kennen, bevor er seinen Inhalt einstellt. – Dispersia

+0

Ja, es war dumm, einen EnumValue zu instantiieren. Alle Eigenschaften von DataType sind korrekt eingestellt, trotzdem erhalte ich diesen Fehler. –

Antwort

6

Für breiteste Kompatibilität Verwendung CellValues.Number als Zellendatentyp.

Gemäß der docs, CellValues.Date ist für Excel 2010, so dass Sie es möglicherweise für die vollständige Abwärtskompatibilität mit Excel 2007 (und möglicherweise anderen Anwendungen) vermeiden möchten.

//broadly supported - earliest Excel numeric date 01/01/1900 
DateTime dateTime = DateTime.Parse(text); 
double oaValue = dateTime.ToOADate(); 
cell.CellValue = new CellValue(oaValue.ToString(CultureInfo.InvariantCulture)); 
cell.DataType = new EnumValue<CellValues>(CellValues.Number); 
cell.StyleIndex = Convert.ToUInt32(_numericDateCellFormatIndex); 


//supported in excel 2010 - not XLSX Transitional compliant 
DateTime dateTime = DateTime.Parse(text); 
cell.CellValue = new CellValue(dateTime.ToString("s")); 
cell.DataType = new EnumValue<CellValues>(CellValues.Date); 
cell.StyleIndex = Convert.ToUInt32(_sortableDateCellFormatIndex); 

Diese earlier more complete answer schlägt vor, dass Excel 2010 nicht den ‚sortierbar‘ selbst CellValues.Date Datentyp standardmäßig nicht verwendet.

Vermutlich liegt der Grund für den Typ CellValues.Date darin, die Einschränkungen des numerischen Datums zu umgehen, wie z. B. das früheste Excel-numerische Datum, das 01/01/1900 ist.

digitalpreservation.gov explains some of the historical intention behind the date cell type, und diese Seite erklärt, dass XLSX Transitional is the version used by mainstream real world applications (getestet im Jahr 2014).

XLSX Strict has a value type for cells of date, using the Complete, Extended Format Calendar representations in ISO 8601. For reasons of backwards compatibility, this typed use of ISO 8601 dates is not permitted in XLSX Transitional.

Late in the ISO standardization process for OOXML, a proposal was made to adopt the ISO 8601 format for dates and times in spreadsheets.

The experts present at the ISO 29500 Ballot Resolution Meeting where votes were held on the outstanding proposals for the OOXML format were primarily experts in XML and in textual documents rather than with spreadsheets

Since the intent of the Transitional variant of ISO 29500 was to be compatible with the existing corpus of .xlsx documents and the applications designed to handle them, an amendment to Part 4 to disallow ISO 8601 dates in the Transitional variant was introduced. Secondly, ISO 8601 is a very flexible format, and any use in a context that aims at interoperability needs to be specific about which particular textual string patterns are expected for dates and times.

... Tests in November 2014 indicated that Google Sheets and Libre Office both created new documents in the Transitional variant

+0

Danke, es funktioniert jetzt. Aber ich verstehe nicht, warum CellValues ​​Nummer und nicht Date sein sollte. Was nutzt Date dann? –

+1

'CellValues.Date' wird weniger breit unterstützt (Antwort aktualisiert). –

+2

Amüsant über diese Frage, als ich Co-Autor der Datumsunterstützung in ISO8601 und arbeitete an dieser Library of Congress Papier. Das Attribut d wurde hinzugefügt, um mehrere am Standardisierungsprozess beteiligte Personen zu beruhigen, die die Tatsache, dass Daten in Tabellenkalkulationen als "Anzahl Tage seit dem 1. Januar 1900" gespeichert wurden, nicht mochten und hofften, dies durch Änderung der Spezifikation zu ändern. Was vielleicht eine gute Idee ist, aber seit Lotus 1-2-3 ist es so. Wie Chris sagt, sollten Sie CellValues ​​verwenden und Daten seit dem 1. Januar 1900 in mehreren Tagen speichern. –

Verwandte Themen