2012-11-01 8 views
22

Ich habe ein Datum im Format "4/5/2011" (Monat/Tag/Jahr) in einer xlsx-Datei in einer der Zellen. Ich versuche, die Datei zu analysieren und diese Daten in einigen Klassen zu laden.Ein Datum von xlsx mit offenem xml sdk lesen

Bisher der Teil, wo ich analysieren die Zelle wie folgt aussieht:

string cellValue = cell.InnerText; 
if (cell.DataType != null) 
{ 
    switch (cell.DataType.Value) 
    { 
     case CellValues.SharedString: 
      // get string from shared string table 
      cellValue = this.GetStringFromSharedStringTable(int.Parse(cellValue)); 
      break; 
    } 
} 

Ich hoffte, dass Datum ein cell.DataType wäre. Die Wahrheit ist, wenn die Zelle mit dem Datum "4/5/2011" analysiert wird, ist der Wert von cell.DataType null und der Wert der Zelle ist "40638" und es ist kein Index für die geteilte Zeichenkettentabelle. (Ich habe das vorher versucht und es endete mit einer Ausnahme.)

Irgendwelche Ideen? Dank

Antwort

26

Open XML speichert Datumsangaben als die Anzahl der Tage ab dem 1. Januar 1900. Nun, das falsche 29.02.1900 als gültigen Tag übersprungen. Sie sollten in der Lage sein, Algorithmen zu finden, die Ihnen helfen, den richtigen Wert zu berechnen. Ich glaube, dass einige Entwickler DateTime.FromOADate() als Helfer verwenden.

Auch die Cell Klasse hat die DataType Eigenschaft als Nummer standardmäßig. Wenn es also null ist, ist es eine Zahl, die in unserem Fall Daten enthält.

Sie gehen nur zu der Shared-String-Tabelle, wenn das gespeicherte Datum vor der Epoche liegt (in diesem Fall 1. Januar 1900). Und dann hält der CellValue der Cell-Klasse den Index in der Shared-String-Tabelle.

+1

Nizza, Parsing mit FromOADate funktioniert tatsächlich! – Santhos

+0

@Santhos, musst du neben "FromOADate" noch etwas einstellen? @VincentTan erwähnt es nur als "Hilfsmethode". –

+2

Das beantwortet es: http://www.dotnetperls.com/fromoadate –

1

ich gleiche Problem hatte - geschaltet EPPlus http://epplus.codeplex.com/

Beachten Sie, dass es LGPL-Lizenz hat. Wenn Sie also Ihre Codebasis benötigen, um vor einem GPL-Problem sicher zu sein, verwenden Sie einfach die Bibliothek, und Ihre ursprüngliche Codebasislizenz ist sicher.

+0

Ich würde lieber bleiben, um XML SDK zu öffnen, aber wenn ich keine Lösung finden werde ich dieses versuchen. Danke – Santhos

+0

Sie haben eine Lösung in openxml SDK, aber es ist viel zu verschachtelt, um es in wenigen Anweisungen zu gehen. Hier ist ein Zeiger - Der Styles-Dokumentteil teilt Ihnen das Zahlenformat mit. Iterieren Sie in ihnen, wählen Sie das passende Element – CKmum

+0

Ich verstehe nicht. Ich würde erwarten, dass das Zahlenformat etwas wie "number: #. ###" oder "date: m/d/y" ist. Diese Nummer, die ich von der Zelle bekommen habe, muss etwas bedeuten. Wissen Sie was das bedeutet? – Santhos

8

können Sie DateTime.FromOADate (41690)

0

Hinzufügen meine 2 Pence wert verwenden. Ich verarbeite eine Vorlage, also weiß ich, dass eine bestimmte Zelle eine DateTime sein soll. Also endete ich in dieser Methode mit einem String-Parameter excelDateTime, der den Zellenwert enthält, der typischerweise eine OADate-Nummer wie "42540.041666666664" ist.

public static bool TryParseExcelDateTime(string excelDateTimeAsString, out DateTime dateTime) 
{ 
    double oaDateAsDouble; 
    if (!double.TryParse(excelDateTimeAsString, out oaDateAsDouble)) //this line is Culture dependent! 
     return false; 
    //[...] 
    dateTime = DateTime.FromOADate(oaDateAsDouble); 

Mein Problem ist, dass der Endverbraucher in Deutschland ist, und weil dies eine Website ist, haben wir das Thread.CurrentThread.CurrentCulture und Thread.CurrentThread.CurrentUICulture auf „DE-de“ gesetzt. Und wenn Sie double.TryParse aufrufen, verwendet es die Kultur, um die Nummer zu analysieren. Also diese Zeile: double.TryParse("42540.041666666664", out oaDate) funktioniert zwar, aber es gibt 42540041666666664 zurück, da in Deutschland der Punkt ein Gruppenseparator ist. DateTime.FromOADate schlägt dann fehl, weil die Nummer außerhalb des Bereichs liegt (minOaDate = -657435.0, maxOaDate = +2958465.99999999).

Das ist ich denke, dass:

  1. unabhängig von der locale auf einen Computer des Benutzers, die OpenXML Belegnummern in einem Standardgebietsschema (US formatierten enthalten invariant in jedem Fall mit dem Punkt als Dezimalzahl? Separator). Ich habe gesucht, aber nicht die Spezifikation dafür gefunden.
  2. Wenn Sie double.TryParse auf eine mögliche OADate-Zeichenfolge tun, sollten wir es mit double.TryParse(excelDateTimeAsString, NumberStyles.Any, CultureInfo.InvariantCulture, out oaDateAsDouble)) tun. Ich benutze CultureInfo.InvariantCulture, aber es sollte der Punkt 1 sein, den ich nicht genau weiß.
+0

Ich hatte genau das gleiche Problem. Ich habe es damit gelöst: 'Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;' –

0

Jede Zelle hat zwei Eigenschaften r (Cellreference) und s (StyleIndex)

StyleIndex für Zahlen 2 und für das Datum ist 3

Datum es in odate ist und Sie können String-Format konvertieren

Wert = DateTime.FromOADate (double.Parse (Wert)). ToShortDateString();