2016-04-16 16 views
4

Ich kann nicht feststellen, wann eine Zelle ein Datum ist.OpenXML - Cell.DateType ist null

Date DataType Cell

bemerkte ich den Datentyp null ist, damit ich nicht unterscheiden kann, ob es sich um eine Nummer eines Datums ist.

ich den nächsten Code verwenden die Zellen zu extrahieren:

WorksheetPart worksheetPart = (WorksheetPart)workbookPart.GetPartById(worksheetId); 
SheetData sheetData = worksheetPart.Worksheet.GetFirstChild<SheetData>(); 
Row[] rows = worksheetPart.Worksheet.Descendants<Row>().ToArray(); 
for (int i = 0; i < rows.Length; i++) 
{ 
    List<Cell> cells = rows[i].Elements<Cell>().ToList(); 
    foreach (var cell in cells) 
    { 
     if (cell.DataType != null && cell.DataType.Value == CellValues.Date) 
      //this line is not hit for some reason 
     } 
    } 
} 

ich etwas fehle?

Antwort

0

Haben Sie versucht, cell.HasValue insteed? Da int und Datetime nicht immer nullfähig sind, hängt es davon ab, wie der Code geschrieben wird.

4

Kurz gesagt ist es null, weil es für numerische und Datumstypen gedacht ist.

OpenXML-Dokumentation auf msdn

Der Wert der Datatype-Eigenschaft ist für numerische und Datumstypen null. Es enthält den Wert CellValues.SharedString für Zeichenfolgen und CellValues.Boolean für boolesche Werte.

Es gibt einen Weg, obwohl zwischen Datum und Anzahl Zellenformaten zu unterscheiden mit dem NumberFormatId auf dem CellFormat. Der Trick besteht darin, herauszufinden, welche ID-Karten zu welchem ​​Format gehören. Sie können herausfinden, welches Format von verwenden, um neue Datei erstellen Excel und eine Zelle in das Format in Frage gesetzt (dh Datum):

enter image description here

Dann Datei 7zip Extrakt treffen und nach innen schauen xl/styles.xml Datei:

enter image description here

im Bild oben Sie diese formatID 14 sehen können übersetzt kurzes Datum. Eine vollständige Liste der Formate finden Sie unter ECMA-376 documentation for Office Open XML formats (Tabelle sollte irgendwo in Teil 4 vergraben sein).

Ich habe eine Enumeration für die häufigsten formatIds:

private enum Formats 
    { 
     General = 0, 
     Number = 1, 
     Decimal = 2, 
     Currency = 164, 
     Accounting = 44, 
     DateShort = 14, 
     DateLong = 165, 
     Time = 166, 
     Percentage = 10, 
     Fraction = 12, 
     Scientific = 11, 
     Text = 49 
    } 

Sie könnten dann eine Hilfsfunktion erstellen, die Sie den formatierten Wert die Art und Weise erhalten Sie möchten:

private static string GetFormattedCellValue(WorkbookPart workbookPart, Cell cell) 
    { 
     if (cell == null) 
     { 
      return null; 
     } 

     string value = ""; 
     if (cell.DataType == null) // number & dates 
     { 
      int styleIndex = (int)cell.StyleIndex.Value; 
      CellFormat cellFormat = (CellFormat)workbookPart.WorkbookStylesPart.Stylesheet.CellFormats.ElementAt(styleIndex); 
      uint formatId = cellFormat.NumberFormatId.Value; 

      if (formatId == (uint)Formats.DateShort || formatId == (uint)Formats.DateLong) 
      { 
       double oaDate; 
       if (double.TryParse(cell.InnerText, out oaDate)) 
       { 
        value = DateTime.FromOADate(oaDate).ToShortDateString(); 
       } 
      } 
      else 
      { 
       value = cell.InnerText; 
      } 
     } 
     else // Shared string or boolean 
     { 
      switch (cell.DataType.Value) 
      { 
       case CellValues.SharedString: 
        SharedStringItem ssi = workbookPart.SharedStringTablePart.SharedStringTable.Elements<SharedStringItem>().ElementAt(int.Parse(cell.CellValue.InnerText)); 
        value = ssi.Text.Text; 
        break; 
       case CellValues.Boolean: 
        value = cell.CellValue.InnerText == "0" ? "false" : "true"; 
        break; 
       default: 
        value = cell.CellValue.InnerText; 
        break; 
      } 
     } 

     return value; 
    } 
+0

Wow .. macht perfekt Sinn @ goodies4uall – thestar