SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

japan.internet.com翻訳記事

Apache POI HSSFによるExcelファイルの読み込み

Java EEのWebプロジェクトにおけるExcelデータの読み込み

  • X ポスト
  • このエントリーをはてなブックマークに追加

ワークブックの要素を識別する

 大抵の人は、Excelファイルがワークシートで構成され、その中にセルが行列の形式で配置されていることは承知しています。Excelファイルがワークブックであることを知っている人も、それを気にすることはめったにないようです。そのため、本稿のサンプル実装では、ワークブックの概念をクライアントから見えなくしています。HSSFライブラリにはJavaでワークブックをExcelと同じように扱うためのメソッドがすべて用意されていますが、ここではファイルからデータを読み込んで利用することにしか関心がありません。つまり、Javaクラスを使って、ユーザーがExcelでするのとまったく同じことを、同じ手順で、なおかつExcelよりもずっと高速でできればよいわけです。必要な手順は次のようになります。

  • ワークシートを開く
  • 見出し行を特定する
  • 行単位でデータを読み込む
  • 列単位でデータを読み込む

値を読み込む

 ワークシートは、HSSFWorkbookオブジェクトから名前またはインデックスで抽出できます。一般に、クライアントアプリケーションでワークシートの名前を重視するのは複数のワークシートがある場合で、インデックスを重視するのはデータを含むワークシートがExcelファイル内に1つだけあると考えられる場合です。今回のクライアントアプリケーションで取り出すのはワークシート内の値だけなので、これから作成するリーダークラスでは、HSSFSheetオブジェクトを取得するためのメソッドを公開する必要すらありません。使いやすい方法で値を返すメソッドがあれば十分なのです。

 汎用性を考えると、データソースとして提供されるスプレッドシートの1行目には、フィールドの名前が含まれているものと仮定するのが安全です。実用的な見地から、入力として受け取るデータでは一定のフォーマットを定義すべきです。ユーザーの入力する任意のレイアウトからフォーマットを判別するようなロジックを工夫することも可能ですが、それは極めて複雑なものとなるでしょう。そこで、最初のユーティリティメソッドでは、与えられたワークシートの1行目の値を返すようにします。

public ArrayList<String> getColNames(int sheetIndex)
{
   ArrayList<String> colNames = new ArrayList<String>();
   HSSFSheet sheet = this.workbook.getSheetAt(sheetIndex);
   HSSFRow   row   = sheet.getRow(0);
   HSSFCell  cell  = null;
   int       cols  = 0;
   if (row != null)
   {
      cols = row.getPhysicalNumberOfCells();
      for (int i = 0; i < cols; i++)
      {
         cell = row.getCell(i);
         if (cell != null && cell.getCellType() == stringCell)
         {
            colNames.add(cell.getRichStringCellValue().getString());
         }
      }
   }
   return colNames;
}

 複数のワークシートを含む入力にも対応できるよう、このメソッドをオーバーロードして、ワークシートの名前を使用するバージョンも用意します。

public ArrayList<String> getColNames(String sheetName)
{
   return getColNames(this.workbook.getSheetIndex(sheetName));
}

 スプレッドシート内の値を表現するには、行単位のデータに対してArrayListをマップするのが簡単なようです。列の名前をキーとして使い、これらのマップをArrayListに格納するわけです。これで、さまざまな目的の値を簡単なコードで読み込むことができ、新しいオブジェクトを生成したり、クライアントアプリケーションにHSSF APIを公開したりしなくて済みます。無論、これが唯一の方法ではありません。私がHSSF APIを初めて実装したとき、これが特に便利だと感じただけです(「Open Source-Based Portal-Lite」のUser-Friendly Updatesを参照)。

/**
 * @param sheetIndex
 * @return ArrayList<Map> where the key is the field names.
 * Assumes first row contains field names
 */
public ArrayList<Map> getMappedValues(int sheetIndex)
{
   ArrayList<String>    colNames    = null;
   ArrayList<Map>       mapArray    = null;
   HSSFRow              row         = null;
   HSSFSheet            sheet       = null;
   int                  sheetRows   = 0;
   int                  rowCols     = 0;
   Map<String, Object>  rowMap      = null;

   sheet     = this.workbook.getSheetAt(sheetIndex);
   sheetRows = sheet.getPhysicalNumberOfRows();
   mapArray  = new ArrayList<Map>(sheetRows - 1);
   colNames  = getColNames(sheetIndex);

   colNames.trimToSize();

   rowCols = colNames.size();

   for (int i = 1; i < sheetRows; i++)
   {
      row    = sheet.getRow(i);
      rowMap = new HashMap<String, Object>(rowCols);
      for (int c = 0; c < rowCols; c++)
      {
         rowMap.put(colNames.get(c), getCellValue(row.getCell(c)));
      }
      mapArray.add(rowMap);
   }
   return mapArray;
}

 ここでも、次のようにオーバーロードすれば、インデックスの代わりにシート名を使えるようになります。

public ArrayList<Map> getMappedValues(String sheetName)
{
   return getMappedValues(this.workbook.getSheetIndex(sheetName));
}

次のページ
読み込んだデータを使用する

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
japan.internet.com翻訳記事連載記事一覧

もっと読む

この記事の著者

japan.internet.com(ジャパンインターネットコム)

japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.comEarthWeb.com からの最新記事を日本語に翻訳して掲載するとともに、日本独自のネットビジネス関連記事やレポートを配信。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

Scott Nelson(Scott Nelson)

ポータルおよびその他の複合Webアプリケーションを専門とするシニアプリンシパルコンサルタント。個人経営の商店からFortune 500(c)に入る多国籍企業まで、大小さまざまな企業向けのアプリケーションを「正しく」かつ「早く」作成した実績を持つ。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/3584 2009/03/16 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング