最近项目中要将较大数据生成Excel2003或Excel2007文件。
由于POI很好的采用了面向接口编程的思想,所以其实生成Excel2003和生成Excel2007的代码多数是可以复用的。
我的做法是:
1.定义Excel2003FileCreator,用来生成Excel2003文件
2.定义Excel2007FileCreator,用来生成Excel2007文件,Excel2007FileCreator extends Excel2003FileCreator。
在Excel2003FileCreator中定义
protected org.apache.poi.ss.usermodel.Workbook workbook;
protected org.apache.poi.ss.usermodel.Sheet sheet;
private org.apache.poi.ss.usermodel.Row row
Workbook,Sheet ,Row均为接口。
只要在生成workbook时,确定是
org.apache.poi.hssf.usermodel.HSSFWorkbook // 生成Excel2003文件用
还是
org.apache.poi.xssf.usermodel.XSSFWorkbook // 生成Excel2007文件用
即可。
后续的Sheet,Row 都是根据 workbook 创建的。
问题的出现:
在对每一个Cell进行设置Style和Value的时候,我先根据DB中的配置,取得每个单元格的格式,再对其进行设定值。
2
3 private static Font getFont(Workbook workbook, int fontHeight, short boldWeight) {
4 // 字体
5 font = workbook.createFont();
6 // Font font = workbook.createFont();
7 font.setFontName("宋体");
8 font.setFontHeightInPoints((short)fontHeight);
9 font.setBoldweight(boldWeight);
10 return font;
11 }
12
再进行设置其他单元格格式。
只列实现代码:
2
3 // 边框
4 if (hasBorder) {
5 style.setBorderBottom((short)1);
6 style.setBorderLeft((short)1);
7 style.setBorderRight((short)1);
8 style.setBorderTop((short)1);
9 }
10
11 // 背景颜色
12 if (isEvenRow) {
13 style.setFillPattern(CellStyle.SOLID_FOREGROUND);
14 style.setFillForegroundColor(colorIndex);
15 }
16
17 // 对齐
18 style.setAlignment(align);
19 style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
20 style.setFont(font);
21 style.setWrapText( true );
22
23 if ( ! "" .equals(excelFmt)) {
24 short format = HSSFDataFormat.getBuiltinFormat(excelFmt);
25 style.setDataFormat(format);
26 }
取得的Style,再调用Cell对象的 cell.setCellStyle(Style) 进行设置格式。
因为这段代码是生成Excel2003和Excel2007时候都要用到的。
生成1w的数据,Excel2003是没有问题的,速度很快。
但是同样的数据,生成Excel2007时,速度慢的可以,让人不能接受。
最后调查得出的结果是:瓶颈在于org.apache.poi.xssf.usermodel.XSSFWorkbook 在生成字体和样式对象时。
问题的解决:
由于对于文件体的单元格设置,每一列几乎是相同的。所以将生成字体和单元格样式的代码做了一些小调整:
2 // 字体 fontMap为全局的Map,用来保存相同字体要求的Font对象
3 // 当要取得字体对象时,先判断是否已经缓存了,如果是,则不需要再创建
4 Font font = fontMap.get(fontHeight + boldWeight);
5 if (font == null) {
6 font = workbook.createFont();
7 // Font font = workbook.createFont();
8 font.setFontName("宋体");
9 font.setFontHeightInPoints((short)fontHeight);
10 font.setBoldweight(boldWeight);
11 fontMap.put(fontHeight + boldWeight, font);
12 }
13 return font;
14 }
取得样式
2 if (style == null ) {
3 // 设定样式,然后将样式缓存在全局的HashMap对象styleMap 中
4 // ..
5 // 略..styleMap.put(***);
6}
7
8 return style;
这样改了之后,速度立刻提高了。
当然,在用完之后,记得clear。
这里要注意的是,缓存HashMap对象中的Key的设定。
Key在组合时要体现出你的单元格格式,又不会因为组合,使得缓存中对象混乱了。
本文为原创,欢迎转载,转载请注明出处BlogJava。