最近使用java的poi库,做一些自动生成的excel报表,遇到了几个坑总结如下。
关于删除excel的行
比如poi提供了removeRow函数,
Row removingRow = sheet.getRow(i);
if (removingRow != null)
sheet.removeRow(removingRow);
但是removeRow只清空了对应row的数据,但是如果当前row有合并的单元格的话,那么removeRow是不会把合并的单元格重新拆开的。
所以,真正要彻底删掉Row,不是用removeRow,而是用shiftRows,即将后面的行往上移。以下函数给出了把指定行一直到excel最后一行全部删掉的函数。
public void removeRows(String sheetName, int startIdx) throws Exception {
Sheet sheet = wb.getSheet(sheetName);
if (sheet == null)
throw new Exception("sheet is null");
int lastrowIdx = sheet.getLastRowNum();
if(startIdx > lastrowIdx)
return;
sheet.shiftRows(lastrowIdx + 1, lastrowIdx + (lastrowIdx - startIdx)+1, startIdx-lastrowIdx-1);
}
关于更改样式和字体
第一个需求是修改当前单元格的样式CellStyle,其它样式均不变。那么采用下面的方法会出现问题:
CellStyle style = cell.getCellStyle();
/* 对style进行修改,省略*/
cell.setCellStyle(style);
修改完发现,不仅当前的Cell的样式发生了变化,其它的Cell也发生了变化。原因是多个单元格共用了一个CellStyle,所以要修改样式,必须要重新创建和当前样式一模一样的样式,再修改。
CellStyle srcStyle = cell.getCellStyle();
CellStyle style = wb.createCellStyle();
style.cloneStyleFrom(srcStyle);
/* 对style进行修改,省略*/
cell.setCellStyle(style);
同理,对Cell的字体进行操作,也会出现类似的问题。所以字体修改,也要先创建和当前Font一模一样的Font,再进行修改。但是poi的Font类没有类似的clone函数,所以只能自己硬写了[泪奔]。
public void setFontColor(CellStyle cs, short colorIndex) {
Font fontNew = this.wb.createFont();
Font fontOld = this.wb.getFontAt(cs.getFontIndex());
fontNew.setFontName(fontOld.getFontName());
fontNew.setFontHeight((short)fontOld.getFontHeight());
fontNew.setBold(fontOld.getBold());
fontNew.setItalic(fontOld.getItalic());
fontNew.setStrikeout(fontOld.getStrikeout());
fontNew.setTypeOffset(fontOld.getTypeOffset());
fontNew.setUnderline(fontOld.getUnderline());
fontNew.setColor(colorIndex);
cs.setFont(fontNew);
}
修改Cell里填充色
按照直觉应该是用CellStyle的setFillBackgroundColor(),毕竟是修改背景色嘛。但是错误!!其实应该用CellStyle的setFillForegroundColor(),即修改前景色。
cs.setFillForegroundColor(colorIndex);
cs.setFillPattern(FillPatternType.SOLID_FOREGROUND);
第二个语句必须加上,否则设置前景色也不会起作用。
关于自定义颜色
poi提供了现成的IndexedColor类,包含了一些常用的颜色,可以用于设置各类填充色和字体颜色。但是如果想自定义颜色的话,对于XSSF类(即office2007以上的文件版本),还比较简单,直接采用以下方法即可:
XSSFColor color = new XSSFColor(new java.awt.Color(r,g,b));
而对于HSSF类,就没有直接设定RGB的地方了,实际上在office 2003里,只提供了56种颜色。带有自定义的颜色的xlsx文件另存为xls文件后,对于56种颜色以外的颜色,系统会自动选择与当前颜色最接近的颜色,从而会使保存的文件颜色失真。
而对于程序实现来说,采用的方法是创建一个颜色去替换56种颜色之一,再使用替换后的颜色即可,如下述代码会将56种颜色中最接近颜色,替换为指定的rgb的颜色,这样以后使用这个颜色的index时,实际上都是用这个rgb的颜色了。
HSSFPalette palette = wb.getCustomPalette();
HSSFColor colorToReplace = palette.findSimilarColor(r, g, b);
short sIndex = colorToReplace.getIndex();
palette.setColorAtIndex(sIndex,
(byte) r, //RGB red (0-255)
(byte) g, //RGB green
(byte) b //RGB blue
);
HSSFCellStyle hcs = (HSSFCellStyle)cs;
fontNew.setColor(sIndex);