2014年3月31日月曜日

poiを使ってみた

気が付きゃ3月も終わりだ('A`)

poiを使ってみた

javaで走らせたり、というかSeleniumでのテスト時に一緒にデータを取って、その結果がExcelとかに出力できたらなー、とか考えたのが始まり

1. poi

ここからダウンロードできるライブラリの一種。簡単に言うと、「Microsoft Documentsにアクセスしやすくするライブラリ」 とのこと。 今回はそのうちの一つであるExcelへのアクセスを手伝ってもらう。
今回は poi-bin-3.10-FINAL-20140208.tar.gz を使用。

2. 環境設定

とりあえずよくわからないので、 
docs以下
LICENCE
NOTICE
以外は全部プロジェクトに放り込んだうえでパスを通した。 examplesとかいるのかなぁ…

3. WorkBookの作成

一つずつ順に。WorkBookはその名の通り作業する場所。ここにExcelファイルの1シートをコピーして作業する。 あくまでコピーなので、最後に書き込まないとExcelファイル自体は更新、書き込みされない点に注意。
    try {

      /* エクセルファイルはどこですか */
      File f = new File(filepath);
      InputStream is = new FileInputStream(f);

      /* ワークブックにアクセス */
      XSSFWorkbook wb = new XSSFWorkbook(is);

    } catch (FileNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
filepathはExcelファイルの在り処。「ファイルが無ければ作る」処理を追加してもいいかも。 WorkBookの作成時には2つもExceptionが発生するので、きちんと捕まえるなど対処が必要。

4. シート、行、列からセルの指定

WorkBookにシートを読み込ませて、徐々に絞っていく感じ。
    try {

      /* エクセルファイルはどこですか */
      File f = new File(filepath);
      InputStream is = new FileInputStream(f);

      /* ワークブックにアクセス */
      XSSFWorkbook wb = new XSSFWorkbook(is);

      /* シートの指定 */
      XSSFSheet sheet = wb.getSheet(sheetname);

      /* シートの定義の最初の行 */
      int firstRow = sheet.getFirstRowNum() + 1;

      /* シートの定義の最終行 */
      int lastRow = sheet.getLastRowNum();

      /* 行を順に上から見ていく。 */
      for (int i = firstRow; i <= lastRow; i++) {

        /* 行情報を取得 */
        XSSFRow row = sheet.getRow(i);

        /* 列の読み込み。 とりあえず 1 で */
        XSSFCell cell = row.getCell(columnno);

      }

    } catch (FileNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
sheetnameとcolumnnoは別途指定。
sheetnameはそのままシートにつける名前。デフォルトは【Sheet1】とかなってるアレ。実はintで順番指定も可能らしい(未検証)。
columnnoは列の番号。 A列が0、B列が1、といった順で対応しているらしい。

作業の順番は、
シートの指定 → 行の指定 → 列の指定
行の指定の際に、シート中にて、【何かしらが列のどこかに記入されている行】の行数が取得できる。今回は事前に項番を振っておいたExcelを読み込んでいるため、項番の分だけ回ってくれる寸法。 【最初の行】の指定の際 +1 しているのは、各列のラベルを設定した結果、その行まで含めて【最初の行】とされてしまったのか、うまくいかなかったため。

もちろん行数をピンポイントに指定してやることも可能。

5. セルの内容の確認

既に記入されていないか確認。
 /* チェック。 いろいろステータスのサポートがあるらしい */
        if (cell != null && cell.getCellType() == Cell.CELL_TYPE_STRING) {

          /* セルの内容がStringなら */
          String cellval = cell.getStringCellValue();

          /* 取得してみる */
          System.out.println(cellval);

        } else if (cell == null || cell.getCellType() == Cell.CELL_TYPE_BLANK) {

          /* ブランクなら */
          System.out.println("からっぽ(・д・`)");
        }
セルの読み込み直後から
Cell.CELL_TYPE_STRING はいわゆるセルの型。数字や日付なんかの指定もあり、読み込み時などに型のチェックができる。「数値が取り出せた場合のみ」なんて条件も可能。

6. 書き込み

実際に書き込む。

/* 指定された列番号のセルを準備する */
    XSSFCell cell = row.getCell(columnNum, Row.CREATE_NULL_AS_BLANK);

    /* 値を適当に書き込む */
    /* TODO Stringじゃなくて数字でよくないかなこれ */
    cell.setCellValue(String.format(" %1$d", 12345));
少し巻き戻って、指定の行から書き込むセルの指定のし直し。columnNumはまた別の列番号。
Row.CREATE_NULL_AS_BLANK は【空のセルとする】的な宣言...?('A`)
setCellValueで値を書き込む。TODOにある通り、なぜ数値をStringで書き込んでいるかは謎(他のとこからコピペしてきたからなんだがな…('A`))

7. Excelに書き込み

先述の通り、ここまでは WorkBook上での出来事。きちんとExcelファイルに放り込んでやらないと更新されない。

      /* 最後にワークブックをファイルに書き込み */
      OutputStream os = new FileOutputStream(f);
      wb.write(os);
これだけ。だけどこれをやらないとExcelファイルには何も起きない…('A`)

8.番外編 -色の指定-

ちょっとだけ戻ってセルの取得あたり。フォントの色やセルの色を付けてみる。
 /* style準備 */
    XSSFCellStyle style = wb.createCellStyle();
    style.setFillPattern(XSSFCellStyle.SOLID_FOREGROUND);

    /* font準備 */
    XSSFFont font = wb.createFont();

    /* 背景色設定 */
    style.setFillForegroundColor(backgroundColor);

    /* フォント設定 */
    font.setColor(fontColor);
    style.setFont(font);

    /* セルにスタイルを反映 */
    cell.setCellStyle(style);
styleがセルの色やら、fontが文字周り。 styleの準備をして、 fontの準備をして、最後にセルにその設定を反映する、という手順。
backgroundColorやfontColorは別宣言。色の指定は HSSFColorクラスが使用可能。たとえば赤であれば、HSSFColor.RED.index で使用できる。
文字の書き込みなどとは別で宣言できるが、当然 7. Excelに書き込み の処理の前にやらないと反映されない。




|ω・`) |Ю .。o0 ( 次は型やら何やらをきれいにしないとな )