業務用のシステムを構築する際に、結構な頻度で考えなくてはいけないのが、エクセル形式のファイル。
様々な企業で幅広く使用されているため、プログラムから扱う場面も少なくありません。
そこで今回は、Javaを利用してエクセルファイルを読み書きするサンプルを作成しておきます。
ApachePOIの概要
(何度も使うので、サクッと使える自分用まとめかな)こういう場合、ApacheのPOIというライブラリを使うと便利ですよねー。
最近のPOIでは、Excel2003形式である「.xls」とExcel2007形式である「.xlsx」の両方のタイプのエクセルファイルを扱うことができます。
そもそも、両形式はどのように異なるのかというと、
- Excel97形式(拡張子が.xls)・・・「Microsoft OLE 2複合ドキュメント形式」(OLE2形式)のフォーマット。バイナリ形式で、オープンな規格ではない。
- Excel2007形式(拡張子が.xlsx)・・・「Office Open XML形式」(OOXML形式)対応のフォーマット。その名の通り、オープンな規格。OpenOfficeもこの形式に対応している。
という感じになっています。
Apache POIも、Ver3.5より、ようやくOOXML形式に対応し、両形式を扱えるようになりました。
なお、その影響で、依存するjarが多くなり、若干分かりにくくなってしまった感は否めないですが。。。
途中から形式が変わってしまったという経緯から、使用するクラス群、パッケージも、それぞれで異なります。
大きくは、
- HSSF系(org.apache.poi.hssf)・・・OLE2形式のファイルフォーマットのJava実装
- XSSF系(org.apache.poi.xssf)・・・OOXML形式のファイルフォーマットのJava実装
に分かれていますが、
- SS系(org.apache.poi.ss)・・・上記の両者を統一的なインターフェースで扱うことができるパッケージ
- SXSSF系・・・3.8-beta3から導入された実装で、非常に大きなエクセルファイルを扱うためのJava実装
も存在していますので、利用用途に応じて使い分けることができます。
では最初にライブラリのインストール、その次に、読み込みのサンプル、最後にエクセルファイルの作成のサンプルを作成します。
ライブラリのダウンロードと設定
最初にPOIをダウンロードしましょう。
ここからダウンロードします。今回は、「POI 3.13」版を使いますので、「Binary Distribution」の「poi-bin-3.13-20150929.zip」としました。
ダウンロードできたら、適当なディレクトリに解凍します。
以下のようなjarファイルが展開されますので、Eclipse等の開発環境でクラスパスに通します。
必要なjarは、直下にできた
・poi-3.13-xxxxxxxx.jar
・poi-ooxml-3.13-xxxxxxxx.jar
・poi-ooxml-schemas-3.13-xxxxxxxx.jar
と、「ooxml-lib」の下に展開された
・xmlbeans-2.6.0.jar
になります。
エクセルファイルの準備と読み込みのjavaサンプル
では、実際にコーディングしていきましょう。
ここでは、SS系のクラスを使って、xlsとxlsxの2種類のファイルの内容を読み込むサンプルとしましょう。
まず、読み込む対象のエクセルファイルを作成します。
適当なディレクトリに、「sample1.xlsx」と「sample1.xls」を作成し、シートの内容は以下のようにします。
日付型や数式も扱えることを確認するために、3列目には日付、4列目には数式「=CONCATENATE(<セル>,”_TEST”)」を定義しました。
javaの具体的なソースは以下の通りです。
import java.io.FileInputStream;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
public class Main {
//適当なディレクトリに書き換えてください
static final String INPUT_DIR = "D:\MyDownload\output\";
public static void main(String[] args) {
try {
String xlsxFileAddress = INPUT_DIR + "Sample1.xlsx";
//共通インターフェースを扱える、WorkbookFactoryで読み込む
Workbook wb = WorkbookFactory.create(new FileInputStream(xlsxFileAddress));
//全セルを表示する
for (Sheet sheet : wb ) {
for (Row row : sheet) {
for (Cell cell : row) {
System.out.print(getCellValue(cell));
System.out.print(" , ");
}
System.out.println();
}
}
wb.close();
}catch (Exception e) {
e.printStackTrace();
} finally {
}
}
private static Object getCellValue(Cell cell) {
switch (cell.getCellType()) {
case Cell.CELL_TYPE_STRING:
return cell.getRichStringCellValue().getString();
case Cell.CELL_TYPE_NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
return cell.getDateCellValue();
} else {
return cell.getNumericCellValue();
}
case Cell.CELL_TYPE_BOOLEAN:
return cell.getBooleanCellValue();
case Cell.CELL_TYPE_FORMULA:
return cell.getCellFormula();
default:
return null;
}
}
}
各セルは、文字列型や数値型、日付型などの「タイプ」をもっていますので、それらをハンドリングするのが、自作の「getCellValue」メソッドになります。
上記のような実行結果になるはずです。
POIでエクセルファイルの作成を行う。
さて次に、エクセルファイルを作成するサンプルを作成していきましょう。
HSSF系、XSSF系はそれぞれWorkbook、Sheet、RowやCellを扱うためのクラスを持っており、それぞれ、
HSSFWorkbook、HSSFSheet、HSSFRow、HSSFCell
XSSFWorkbook、XSSFSheet、XSSFRow、XSSFCell
となっています。ただ、上記にも述べたSS系(org.apache.poi.ss)パッケージを使うと、共通のRow、Cellクラスで扱えるため、変えるのはWorkbookのクラス部分だけですみます。
RowとCellの基本的な概念は以下の図を参考にしてください。
import java.io.FileOutputStream;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.WorkbookUtil;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class MainWrite {
//適当なディレクトリに書き換えてください
static final String INPUT_DIR = "D:\MyDownload\output\";
public static void main(String[] args) {
try {
//xlsの場合はこちらを有効化
//Workbook wb = new HSSFWorkbook();
//FileOutputStream fileOut = new FileOutputStream("workbook.xls");
//xlsxの場合はこちらを有効化
Workbook wb = new XSSFWorkbook();
FileOutputStream fileOut = new FileOutputStream(INPUT_DIR + "sample2.xlsx");
String safeName = WorkbookUtil.createSafeSheetName("['aaa's test*?]");
Sheet sheet1 = wb.createSheet(safeName);
CreationHelper createHelper = wb.getCreationHelper();
//Rows(行にあたる)を作る。Rowsは0始まり。
Row row = sheet1.createRow((short)0);
//cell(列にあたる)を作って、そこに値を入れる。
Cell cell = row.createCell(0);
cell.setCellValue(1);
row.createCell(1).setCellValue(1.2);
row.createCell(2).setCellValue(
createHelper.createRichTextString("sample string"));
row.createCell(3).setCellValue(true);
wb.write(fileOut);
fileOut.close();
}catch (Exception e) {
e.printStackTrace();
} finally {
}
}
}
上記のサンプルでは、WorkbookUtilクラスの「createSafeSheetName」というメソッドを使用してシート名を作成していますが、これは、シートに使用できない文字をスペースに置き換え、安全な文字列を生成するためです。
また、CreationHelperというクラスも使用しています。このクラスは、いくつか、セルにセットする値を簡便に生成するメソッドを持っていますので、利用すると便利です。