用到的jar包是 POI 3.8,注意导包的时候,那几个包都要导进去,下包就不用说了吧,官网上有。http://poi.apache.org/
接着是个工具类,无意中在网上发现了,感觉封装的不错,我就稍微修改了下,导出大数据量(30W数据,70列)到EXCEL2007,目前没有出现内存溢出问题。
import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Calendar; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.DataFormat; 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.xssf.streaming.SXSSFWorkbook; public class ExcelWriter { // 定制浮点数格式 private static String NUMBER_FORMAT = "#,##0.00"; // 定制日期格式 private static String DATE_FORMAT = "m/d/yy"; // "m/d/yy h:mm" private OutputStream out = null; private Workbook workbook = null; private Sheet sheet = null; private Row row = null; public ExcelWriter() { } public ExcelWriter(OutputStream out) { this.out = out; this.workbook = new SXSSFWorkbook(128);//POI3.8最新的API,解决问题的关键。 this.sheet = workbook.createSheet(); } /** * 导出Excel文件 * @throws IOException */ public void export() throws FileNotFoundException, IOException { try { workbook.write(out); out.flush(); out.close(); } catch (FileNotFoundException e) { throw new IOException(" 生成导出Excel文件出错! ", e); } catch (IOException e) { throw new IOException(" 写入Excel文件出错! ", e); } } /** * 增加一行 * @param index 行号 */ public void createRow(int index) { this.row = this.sheet.createRow(index); } /** * 获取单元格的值 * @param index 列号 */ public String getCell(int index){ Cell cell = this.row.getCell((short) index); String strExcelCell = ""; if (cell != null) { // add this condition // judge switch (cell.getCellType()) { case Cell.CELL_TYPE_FORMULA: strExcelCell = "FORMULA "; break; case Cell.CELL_TYPE_NUMERIC: { strExcelCell = String.valueOf(cell.getNumericCellValue()); } break; case Cell.CELL_TYPE_STRING: strExcelCell = cell.getStringCellValue(); break; case Cell.CELL_TYPE_BLANK: strExcelCell = ""; break; default: strExcelCell = ""; break; } } return strExcelCell; } /** * 设置单元格 * @param index 列号 * @param value 单元格填充值 */ public void setCell(int index, int value) { Cell cell = this.row.createCell((short) index); cell.setCellType(Cell.CELL_TYPE_NUMERIC); cell.setCellValue(value); } /** * 设置单元格 * @param index 列号 * @param value 单元格填充值 */ public void setCell(int index, double value) { Cell cell = this.row.createCell((short) index); cell.setCellType(Cell.CELL_TYPE_NUMERIC); cell.setCellValue(value); CellStyle cellStyle = workbook.createCellStyle(); // 建立新的cell样式 DataFormat format = workbook.createDataFormat(); cellStyle.setDataFormat(format.getFormat(NUMBER_FORMAT));//设置cell样式为定制的浮点数格式 cell.setCellStyle(cellStyle); // 设置该cell浮点数的显示格式 } /** * 设置单元格 * @param index 列号 * @param value 单元格填充值 */ public void setCell(int index, String value) { Cell cell = this.row.createCell((short) index); cell.setCellType(Cell.CELL_TYPE_STRING); cell.setCellValue(value); } /** * 设置单元格 * @param index 列号 * @param value 单元格填充值 */ public void setCell(int index,Calendar value) { Cell cell = this.row.createCell((short) index); cell.setCellValue(value.getTime()); CellStyle cellStyle = workbook.createCellStyle(); // 建立新的cell样式 DataFormat format = workbook.createDataFormat(); cellStyle.setDataFormat(format.getFormat(DATE_FORMAT)); // 设置cell样式为定制的日期格式 cell.setCellStyle(cellStyle); // 设置该cell日期的显示格式 } public static void main(String[] args) { System.out.println(" 开始导出Excel文件 "); File f = new File("C:\\qt.xls"); ExcelWriter e = new ExcelWriter(); try { e = new ExcelWriter(new FileOutputStream(f)); } catch (FileNotFoundException e1) { e1.printStackTrace(); } e.createRow(0); e.setCell(0, "试题编码 "); e.setCell(1, "题型"); e.setCell(2, "分值"); e.setCell(3, "难度"); e.setCell(4, "级别"); e.setCell(5, "知识点"); e.createRow(1); e.setCell(0, "t1"); e.setCell(1, 1); e.setCell(2, 3.0); e.setCell(3, 1); e.setCell(4, "重要"); e.setCell(5, "专业"); try { e.export(); System.out.println(" 导出Excel文件[成功] "); } catch (IOException ex) { System.out.println(" 导出Excel文件[失败] "); ex.printStackTrace(); } } }
这个只是个util。接着你就可以运用到你的工程中去了。下面是个测试类。
import java.io.BufferedOutputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; public class TestExcelPOI { public static void main(String[] args) throws FileNotFoundException { String newFileName = "test_performance.xlsx"; int rows = 100000; int cols = 70; BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(newFileName)); ExcelWriter excelWriter = new ExcelWriter(out); long start =System.currentTimeMillis(); for (int rowNum = 0; rowNum < rows; rowNum++){ excelWriter.createRow(rowNum); for (int colNum = 0; colNum < cols; colNum++) { String value = rowNum + "_" + colNum;//模拟数据 excelWriter.setCell(colNum, value); } } try{ excelWriter.export(); System.out.println(" 导出Excel文件[成功]"); } catch (IOException ex) { System.out.println(" 导出Excel文件[失败]"); ex.printStackTrace(); } long end =System.currentTimeMillis(); double seconds = (end -start)/Math.pow(10, 3); System.out.println(seconds); } } /***************运行结果************************** *导出Excel文件[成功] * 48.293 *************************************************/本人运行的30W,差不多2分钟左右,感觉还是比这个快些的。
总结:
开始没用POI最新的API,还是很容易就溢出了,大概6000行,70列,就溢出,效果不好,用了POI3.8 的最新API,请注意ExcelWriter里面的代码。
在此之前还尝试过csv和table导出数据,csv是用逗号分隔,table用标签把数据封装起来。这两个还没出现内存溢出,也没做具体的测试,有个缺点就是格式不好控制。如果你对格式要求不高,或者数据只是用来看的,可以考虑这种。
还有就是写成多个EXCEL,然后在合并,可惜效果也不佳。
这是问题的链接,部分项目代码可以参考一下。
http://topic.csdn.net/u/20120821/16/ac109bbe-c002-4490-93da-bf02b42f0400.html