2012-11-01 61 views
22

いずれかのセルのxlsxファイルに "4/5/2011"(月/日/年)の形式の日付があります。私はファイルを解析し、それらのデータをいくつかのクラスでロードしようとしています。xlsxからopen xml sdkを使用して日付を読み取る

これまでのところ、私は、細胞を解析する部分は次のようになります。

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; 
    } 
} 

私は日付がcell.DataTypeだろうと期待しました。真実は、 "2011年4月5日"の日付でセルを解析すると、cell.DataTypeの値がnullであり、セルの値が "40638"であり、共有文字列テーブルのインデックスではありません。 (私は前にそれを試して、それは例外と終わった。)

任意のアイデア?私は同じ問題を持っていた おかげ

答えて

26

オープンXMLは、1900年1月1日からの日数として日付を格納します。正しく、1900年2月29日を有効日としてスキップします。あなたは正しい値を計算するのに役立つアルゴリズムを見つけることができるはずです。一部の開発者はDateTime.FromOADate()をヘルパーとして使用しています。

また、Cellクラスは、デフォルトでNumberとしてDataTypeプロパティを持ちます。だから、もしそれがnullなら、それは私たちの場合の日付を含む数字です。

保存された日付がエポック(この場合は1900年1月1日)前である場合にのみ、共有文字列テーブルに移動します。その場合、CellクラスのCellValueは共有文字列テーブルのインデックスを保持します。

+1

FromOADateで解析すると、実際にうまくいきます! – Santhos

+0

@Santhos、あなたは 'FromOADate'以外の調整が必要ですか? @ VincentTanはそれを「ヘルパーメソッド」としか言いません。 –

+2

それはそれに答える:http://www.dotnetperls.com/fromoadate –

1

は - それはLGPLライセンスを持っていることをEPPlus http://epplus.codeplex.com/

ノートに切り替えます。したがって、GPLの問題から安全なコードベースが必要な場合は、ライブラリをそのまま使用し、元のコードベースライセンスは安全です。

+0

私はむしろopen xml sdkに固執したいと思いますが、私が解決策を見つけることができなければ、私はこれを試してみます。ありがとう – Santhos

+0

あなたはopenxml sdkのソリューションを持っていますが、それはあまりにも複雑なので、いくつかのステートメントでそれを取得することです。ここにポインタがあります - スタイルdocumentpartはnumberformatを伝えます。それらの中で繰り返し、一致する要素を選択してください – CKmum

+0

私は理解していません。私はその数字の形式が "数字:##。##"や "日付:m/d/y"のようなものであることを期待しています。私が細胞から得た数は、何かを意味する必要があります。それが何を意味するか知っていますか? – Santhos

8

あなたは私の2ペンスの価値を追加するDateTime.FromOADate(41690)

0

を使用することができます。 テンプレートを処理しているので、特定のセルがDateTimeであることがわかります。 だから、私はこのメソッドで、通常は "42540.041666666664"のようなOADateの数字になるセル値を含む文字列パラメータexcelDateTimeで終了します。

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); 

私の問題は、エンドユーザーがドイツであり、これはウェブサイトであるため、私たちは「DE-ド」にThread.CurrentThread.CurrentCultureとThread.CurrentThread.CurrentUICultureを設定したということです。 double.TryParseと呼ぶと、番号を解析するためにカルチャが使用されます。だからこの行:double.TryParse("42540.041666666664", out oaDate)実際には動作しますが、それはドイツのように42540041666666664を返します。ドットはグループセパレータです。番号が範囲外(minOaDate = -657435.0, maxOaDate = +2958465.99999999)なのでDateTime.FromOADateが失敗します。

この私がいると思います?

  1. は関係なく、ユーザーのマシン上のロケールの、OpenXMLドキュメントは、デフォルトロケール(米国不変でフォーマットされた番号が含まれているどのような場合には、小数点以下のようにドットで?セパレータ)。私は検索しましたが、この仕様は見つかりませんでした。
  2. 潜在的なOADate文字列にdouble.TryParseを実行する場合は、double.TryParse(excelDateTimeAsString, NumberStyles.Any, CultureInfo.InvariantCulture, out oaDateAsDouble))とする必要があります。私はCultureInfo.InvariantCultureを使用していますが、それは何のポイント1であっても、私は確かに分かりません。
+0

私はまったく同じ問題を抱えていました。私はこれでこれを解決しました: 'Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;' –

0

各セルは、2つのプロパティは、(CellReference)rをしているとs(StyleIndex)番号の

StyleIndexが2で、日付のために、それは大館にある3

日であり、あなたは、文字列形式に変換することができます

value = DateTime.FromOADate(double.Parse(value))。ToShortDateString();

関連する問題