2010年08月14日

POIでセルの値をとるのは大変 日付編(1)

前回はPOIで値を取得することが一筋縄ではいかないこと、数値タイプについての解決策(妥協?)をご紹介しました。
今回は日付についての解決策をご紹介します。

POIで日付タイプであると判定する場合、
 1.セルタイプが数値であること
 2.書式が日付型であること
を確認して値の取得を行います。
一般的には
  switch(cell.getCellType()) {
   ・・・
  case Cell.CELL_TYPE_NUMERIC:
    if (DateUtil.isCellDateFormatted(cell)) {
      // 日付型として値を取得
      return cell.getDateCellValue();
    }
    // それ以外は数値のセルとして値を取得
    ・・・
    break;
  case ・・・
のようになると思います。
前回同様に「表示されているとおりの内容をString型で取得」するには、セルのフォーマットを取得して変換が必要になります。
ここで下記の大きな2つの問題があります。
 1.isCellDateFormatted()が日付として認識できないフォーマットがある
 2.フォーマットの文字列を取得できない場合がある
根本的には一緒のようですが、ひとつずつ問題を見ていきましょう。

isCellDateFormatted()が日付として認識できないフォーマットがある
例えば「[$-411]ggge"年"m"月"d"日"」は日付として認識してくれません。
ユーザ定義も含めて一切合財すべてのケースを救ってほしいとは思いませんが、Excelでセルの書式設定する際に選択肢にあがっている程度のものはなんとかしてほしいと願うのは人情ではないでしょうか。
isCellDateFormatted()は、最初にセルのフォーマットインデックスを調べて、Excelの内部的に「日付フォーマット」と認識しているものである場合にtrueを、
それ以外の場合はフォーマットの文字列をチェックして日付フォーマットの文字列のみで構成されているかで判定します。
上記の例では、内部的な日付フォーマットでもないし、和暦の部分が日付フォーマットの文字列ではないと認識されてしまうわけです。

フォーマットの文字列を取得できない場合がある
どんな場合にフォーマットの文字列を取得できないのでしょうか。
数値編の場合同様、DataFormatter#formatCellValue()を使うと、表示されている内容の文字列で取得できます。
ところが、このメソッドは日付の判定にDateUtil#isCellDateFormatted()を使用しています。
つまり、問題点1と同じ問題を含んでいるわけです。
また、CellStyle#getDataFormatString()でフォーマットを取得しても、Excelでの表現なので、このままではJava側で文字列への変換に使用できません。

ではどうやって解決すればよいのでしょう?
ここまで長々と問題点を記載してきましたが、検索の結果から見ると、POIの開発中にも議論がなされていたようで、
「インデックスによる解決は、常に同じフォーマットになるか保証できないのでやめたほうがよい」とのこと。
また、ExcelとOpenOffice間ですら、日付としての認識に相違がある(らしい)ことから、
またしても妥協をします。
日本のお客様向けの開発をしていて、和暦に適応できないのは困るので、対応したいと思います。
解決方法の方針として、
 1.java.text.DateFormatをもつenum CellDateFormatを定義
 2.CellDateFormatに変換を行いたいフォーマットを登録
 3.日付の判定にDateUtil#isCellDateFormatted()を使用し、
   falseだった場合でも、CellDateFormatに存在する場合にtrueとする
 4.CellDateFormatから返されるjava.text.DateFormatで文字列に変換する
とし、次回に具体的なコーディングをしていきます。
タグ:Poi java
posted by しん at 11:33| Comment(0) | POI | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。