※追記※


POIとは

  1. Jakarta-POI
  2. MS-WindowsのOLE(Object Linking and Embedding)オブジェクトをJavaから操作しようというライブラリ
  3. POI(Poor Obfuscation Implementation)の構成
    POIFS(POI File System)OLEドキュメントを読み書きするためのAPI
    HSSF(Horrible Spread Sheet Format)Excel97形式のOLEドキュメントを読み書きするためのAPI。POIFSを利用
    HFD(Horrible Document Format)Word97形式のOLEドキュメント読み書きするためのAPI。POIFSを利用
    HPSF(Horrible Property Set Format)OLEドキュメントのファイル情報(作成者名など)を読み取るためのAPI。今のところ出力する機能はない

HSSFのデータ構造

Excelワークシートをいろいろといじることができますが、 ここでは以下の二つの場合を想定して必要なクラスとメソッドを整理します。


HSSFWorkbook(Excel Workbookファイル)
 |
 +---HSSFSheet(Work Sheet)
      |
      +---HSSFRow(行)
            |
            +---HSSFCell(セル)
 
poi.png
 
  1. HSSFWorkbook (最初のシート番号は0)
    メソッド機能
    読み込み
    HSSFWorkbook()新しいWorkbookを作る
    HSSFWorkbook(InputStream?)既存のWorkbookを読み込む
    書き込み
    void write(OutputStream?)Workbookの内容をファイルに書き出す
    byte[] getbytes()Workbookの内容をbyte[]に書き出す
    Worksheet操作
    HSSFSheet cloneSheet(シート番号)シートをコピーする
    HSSFSheet createSheet()シートを作成する
    HSSFSheet getSheet(シート名)シートを取得する
    HSSFSheet getSheetAt?(シート番号)シートを取得する
    int getSheetIndex?(シート名)シート番号を取得する
    String getSheetName?(シート番号)シートの名前を取得する
    void removeSheetAt?(シート番号)シートの削除
    HSSFSheet setSheetName?(シート番号,シート名)シートに名前を付ける
    HSSFSheet setSheetName?(シート番号,シート名,エンコード)シート名に日本語を使う時には、HSSFWorkbook.ENCODING_UTF_16 にする
     
  2. HSSFSheet (最初の行番号は0)
    メソッド機能
    int getFirstRowNum?()データのある最初の行の行番号を取得する
    int getLastRowNum?()データのある最後の行の行番号を取得する
    Iterator rowIterator()データのある行をRowのIteratorで取得する
    HSSFRow getRow(行番号)行を取得する
    HSSFRow createRow(行番号)行を作成する
    void removeRow(HSSFRow)行を削除する
     
  3. HSSFRow (最初の列番号は0)
    メソッド機能
    int getFirstCellNum?()データのある最初の列の列番号を取得する
    int getLastCellNum?()データのある最後の列の列番号を取得する
    Iterator CellIterator?()データのある列をCellのIteratorで取得する
    HSSFCell getCell(列番号)セルを取得する
    HSSFCell createCell(列番号)セルを作成する
    void removeCell(HSSFCell)セルを削除する
     
  4. HSSFCell
    メソッド機能
    int getCellType?()セルの型を取得する
    Date getDateCellValue?()セル値を日時として取得する
    double getNumericCellValue?()セル値を数値として取得する
    String getStringCellValue?()セル値を文字列として取得する
    void setCellValue?(セル値)セルに値を書き込む。セル値の型は、double,String,Dateなどが使える
    void setEncoding(encoding)セルの値に日本語を書き込む場合には HSSFCell.ENCODING_UTF_16 を設定する
     
    1. セルの型(getCellType?()の返値
      意味
      HSSFCell.CELL_TYPE_BLANK
      HSSFCell.CELL_TYPE_BOOLEAN論理値
      HSSFCell.CELL_TYPE_ERRORエラー
      HSSFCell.CELL_TYPE_FORMULA
      HSSFCell.CELL_TYPE_NUMERIC数値
      HSSFCell.CELL_TYPE_STRING文字列
       
    2. 日付型かどうかの判定
      • 日付型の時、getCellType?() の返値は HSSFCell.CELL_TYPE_NUMERIC
      • 続けて、HSSFDateUtil?.isCellDateFormmated?(cell) を実行し、返値がtrueならば日付型

サンプル

  1. 準備したワークシート
    Sheet1.PNG
     
    Sheet2.PNG
  2. ソースコード
     import java.io.FileInputStream;
     import java.io.FileOutputStream;
     
     import org.apache.poi.hssf.usermodel.HSSFCell;
     import org.apache.poi.hssf.usermodel.HSSFDateUtil;
     import org.apache.poi.hssf.usermodel.HSSFRow;
     import org.apache.poi.hssf.usermodel.HSSFSheet;
     import org.apache.poi.hssf.usermodel.HSSFWorkbook;
     
     public class POIExam {
      
      public static Object cell2Object(HSSFCell cell) {
        switch (cell.getCellType()) {
        case HSSFCell.CELL_TYPE_BLANK:
          return "";
     
        case HSSFCell.CELL_TYPE_BOOLEAN:
          return new Boolean(cell.getBooleanCellValue());
     
        case HSSFCell.CELL_TYPE_ERROR:
          return null;
     
        case HSSFCell.CELL_TYPE_FORMULA:
          return "";
     
        case HSSFCell.CELL_TYPE_NUMERIC:
     
          if (HSSFDateUtil.isCellDateFormatted(cell)) {
            return cell.getDateCellValue();
          } else {
            double val = cell.getNumericCellValue();
     
            if (val == Math.ceil(val)) {
              return new Integer((int) val);
            } else {
              return new Double(val);
            }
          }
     
        case HSSFCell.CELL_TYPE_STRING:
          return cell.getStringCellValue();
     
        default:
          return null;
        }
      }
     
      public static void main(String[] args) {
        try {
          // ワークブックの取得
          HSSFWorkbook book = new HSSFWorkbook(new FileInputStream(
              "TestData.xls"));
     
          int sheets = book.getNumberOfSheets();
          System.out.println("シート数\t: " + sheets);
     
          for (int sheetNumber = 0; sheetNumber < sheets; sheetNumber++) {
            System.out.println("----------------------------------------");
            System.out.println(sheetNumber + ":"
                + book.getSheetName(sheetNumber));
     
            HSSFSheet sheet = book.getSheetAt(sheetNumber);
            int firstRowNum = sheet.getFirstRowNum();
            int lastRowNum = sheet.getLastRowNum();
     
            System.out.println("  有効行: " + firstRowNum + "〜" + lastRowNum);
     
            for (int rowNum = firstRowNum; rowNum <= lastRowNum; rowNum++) {
              System.out
                  .println("   ----------------------------------------");
     
              HSSFRow row = sheet.getRow(rowNum);
     
              if (row == null) {
                continue;
              }
     
              int firstCellNum = row.getFirstCellNum();
              int lastCellNum = row.getLastCellNum();
     
              System.out.print("    " + row.getRowNum() + "行目");
              System.out.print("(有効列: " + firstCellNum + "〜"
                  + lastCellNum + ") = ");
     
              for (int cellNum = firstCellNum; cellNum < lastCellNum; cellNum++) {
                HSSFCell cell = row.getCell((short) cellNum);
     
                if (cell == null) {
                  continue;
                }
     
                System.out.print(cell2Object(cell) + " | ");
              }
     
              System.out.println("");
            }
          }
     
          // 新しいデータの追加
          HSSFSheet newSheet = book.createSheet("Sheet" + (sheets + 1));
          HSSFRow newRow = newSheet.createRow(0);
          HSSFCell newCell = newRow.createCell((short) 0);
     
          newCell.setEncoding(HSSFCell.ENCODING_UTF_16);
          newCell.setCellValue("新しいワークシート");
     
          book.write(new FileOutputStream("TestData2.xls"));
     
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
     }
    
  3. 実行結果 シート数 : 2
    ----------------------------------------
    0:Sheet1
     有効行: 0〜1
       ----------------------------------------
       0行目(有効列: 0〜4) = R1C1 | R1C3 | 
       ----------------------------------------
       1行目(有効列: 0〜4) = R2C2 | R2C3 | R2C4 | 
    ----------------------------------------
    1:Sheet2
     有効行: 0〜2
       ----------------------------------------
       0行目(有効列: 0〜3) = R1C1 | 
       ----------------------------------------
       1行目(有効列: 0〜3) = R2C2 | 
       ----------------------------------------
       2行目(有効列: 0〜3) = R3C2 | R3C3 | 
  4. 作成したワークシート
    Sheet3.PNG

はまったところ

  1. HSSFRow.getFirstCellNum?() / HSSFRow.getLastCellNum?() が返す値は、WorkSheet?全体の矩形の左端と右端
    ABCDE
    1OO
    2OOOO
    3OOO
    4OOO
    5O
    • どの行のFirstCellNum?()も0
    • どの行のLastCellNum?()も5
       
  2. HSSFRow.getFirstCellNum?() / HSSFRow.getLastCellNum?() が返す値はあまり信用しない方が良い
    • 厳密にFirstCellNum?()列からLastCellNum?()列までデータがあると期待しないで、その範囲内にデータがあると考える。65535列全部見るよりはマシ。
       
  3. HSSFRow.CellIterator?() から返ってくる Iterator は Cell の順番が滅茶苦茶
  4. cell.getStringCellValue?()には、両端にスペースが混じることがある。
    cell.getStringCellValue().trim()が吉
     
  5. 値を書き込む時には、先にエンコーディングを指定する
    ○
    cell.setEncoding(HSSFCell.ENCODING_UTF_16);
    cell.setCellValue(obj.toString()); 
    
    ×
    cell.setCellValue(obj.toString()); 
    cell.setEncoding(HSSFCell.ENCODING_UTF_16);

セルに色をつける

HSSFFont fontStyle = book.createFont();
fontStyle.setColor(HSSFColor.WHITE.index);

HSSFCellStyle headerStyle = book.createCellStyle();
headerStyle.setFillForegroundColor(HSSFColor.BLACK.index);
headerStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); 
headerStyle.setFont(fontStyle);

cell.setCellStyle(style);

参考文献

  1. Jakarta-POI, http://jakarta.terra-intl.com/poi/
  2. Java Sticky Note, http://www.salicaceae.net/
  3. 青木 淳夫, JakartaPOIでExcel形式の帳票を出力する [中級] POIライブラリによるExcel形式ファイルのダウンロード方法 , Code Zine http://codezine.jp/a/article.aspx?aid=41
  4. POIでグラフ, @IT会議室 > Java Solution 会議室, http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=10824&forum=12&4

Java#Jakarta


添付ファイル: filepoi.png 2073件 [詳細] fileSheet3.PNG 2023件 [詳細] fileSheet2.PNG 1941件 [詳細] fileSheet1.PNG 2000件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS   sitemap
Last-modified: 2013-01-23 (水) 01:40:26 (1410d)
ISBN10
ISBN13
9784061426061