POI/Tips のバックアップ(No.2) |
|
以下の記載は、POI version2.5.1を前提にしています。
[参考URL]
マクロの残骸が残っているのか何なのかよくわからないのですが、何らかの設定を行ったExcelファイルをPOIで読み込んで、ファイル出力したものを、Excel 2002以降で開こうとすると、以下のようなダイアログが出ます。
ちなみに、同ファイルをExcel2000で開いた場合はダイアログは出ません。また、1から作ったキレイなExcelファイルであればExcel2002でも問題ありません。
行の挿入機能が実装されていません。「行の新規作成」と「行の移動」機能を使って、独自に実装することになります。例えば、以下のような実装になります。
/**
* Excelシートに行を挿入します。
* @param sheet POIのExcelシートオブジェクト
* @param rowNum 行の番号
* @param templateRowNum コピー元となる行の番号
*/
private void insertRow(HSSFSheet sheet, int rowNum, int templateRowNum) {
try {
sheet.shiftRows(rowNum, sheet.getPhysicalNumberOfRows(), 1, true, false);
HSSFRow row = sheet.createRow(rowNum);
HSSFRow templateRow = sheet.getRow(templateRowNum);
// 行の高さを複製する。
row.setHeight(templateRow.getHeight());
row.setHeightInPoints(templateRow.getHeightInPoints());
for (int i = 0; i < templateRow.getPhysicalNumberOfCells(); i++) {
//(1)オリジナル行のCellStyleを流用する。
//オリジナル行のCellStyleに変更を加えたときには、
//新規セルにも反映される。
HSSFCell templateCell = templateRow.getCell((short)i);
HSSFCell cell = row.createCell((short)i);
cell.setCellStyle(templateCell.getCellStyle());
//(2)オリジナルから複製したCellStyleを使う。
//オリジナル行のCellStyleに変更を加えても、
//新規セルには反映されない。
//cloneCellStyleは独自実装
//cell.setCellStyle(cloneCellStyle(templateCell.getCellStyle()));
//cell.setCellType(templateCell.getCellType());
//cell.setCellFormula(templateCell.getCellFormula());
}
} catch (NullPointerException npe) {
throw new NullPointerException("Excel行追加でエラーが発生しました。");
}
}
この際、セルの書式設定をするオブジェクトHSSFCellStyleについては、コピー元のセルと同じインスタンスを共用していることに注意が必要です。つまり、片方の書式設定を変更すると、もう一方も変わってしまいます。
そうしたくない場合は、HSSFCellStyleのインスタンスを複製する必要がありますが、そのメソッドも自作する必要があるようです。また、セルの書式設定を作成する際には、「セルの書式の組み合わせが約4000を超えられない」というExcelの制約に違反しないように注意する必要があります。つまりHSSFCellStyleインスタンスを4000以上作成することはできません。
/**
* セルの書式設定を複製します。
* @param originalStyle 複製元となるPOIのセルスタイルオブジェクト
* @return 複製されたPOIのセルスタイルオブジェクト
*/
private HSSFCellStyle cloneCellStyle(HSSFCellStyle originalStyle) {
HSSFCellStyle newStyle = workbook.createCellStyle();
newStyle.setAlignment(originalStyle.getAlignment());
newStyle.setBorderBottom(originalStyle.getBorderBottom());
newStyle.setBorderLeft(originalStyle.getBorderLeft());
newStyle.setBorderRight(originalStyle.getBorderRight());
newStyle.setBorderTop(originalStyle.getBorderTop());
newStyle.setBottomBorderColor(originalStyle.getBottomBorderColor());
newStyle.setDataFormat(originalStyle.getDataFormat());
newStyle.setFillBackgroundColor(originalStyle.getFillBackgroundColor());
newStyle.setFillForegroundColor(originalStyle.getFillForegroundColor());
newStyle.setFillPattern(originalStyle.getFillPattern());
newStyle.setFont(workbook.getFontAt(originalStyle.getFontIndex()));
newStyle.setHidden(originalStyle.getHidden());
newStyle.setIndention(originalStyle.getIndention());
newStyle.setLeftBorderColor(originalStyle.getLeftBorderColor());
newStyle.setLocked(originalStyle.getLocked());
newStyle.setRightBorderColor(originalStyle.getRightBorderColor());
newStyle.setRotation(originalStyle.getRotation());
newStyle.setTopBorderColor(originalStyle.getTopBorderColor());
newStyle.setVerticalAlignment(originalStyle.getVerticalAlignment());
newStyle.setWrapText(originalStyle.getWrapText());
return newStyle;
}
Excelの「式」形式になっているセルに値を代入しようとしたり、「日付」形式のセルに文字列を代入しようとしたりすると、例外が発生したり、意図しない表示になります。セルに値を代入する時には、セルの表示形式も指定した方が安全かもしれません。
POIは、Excelのヘッダーやフッターも扱うことはできます。しかし、ヘッダーやフッターについては、2byte文字のサポートがされていませんので、日本語の文字は化けてしまいます。しかし、有志の方が作成してくださっているパッチを当てると、ヘッダーやフッターでも日本語が使えるようになります。
結合されたセルが含まれているシートや行を複製する際に、その結合状態を保持することは、かなり困難です。一応、POIでもセルの結合(Region)をサポートしているのですが、結合状態の取得、設定は共にやや面倒です。