批量导出大数据量到EXCEL
用到的jar包是POI3.8,注意导包的时候,那几个包都要导进去,下包就不用说了吧,官网上有。http://poi.apache.org/
接着是个工具类,无意中在网上发现了,感觉封装的不错,我就稍微修改了下,导出大数据量(30W数据,70列)到EXCEL2007,目前没有出现内存溢出问题。
[html]viewplaincopyprint?
importjava.io.File;
importjava.io.FileNotFoundException;
importjava.io.FileOutputStream;
importjava.io.IOException;
importjava.io.OutputStream;
importjava.util.Calendar;
importorg.apache.poi.ss.usermodel.Cell;
importorg.apache.poi.ss.usermodel.CellStyle;
importorg.apache.poi.ss.usermodel.DataFormat;
importorg.apache.poi.ss.usermodel.Row;
importorg.apache.poi.ss.usermodel.Sheet;
importorg.apache.poi.ss.usermodel.Workbook;
importorg.apache.poi.xssf.streaming.SXSSFWorkbook;
publicclassExcelWriter{
//定制浮点数格式
privatestaticStringNUMBER_FORMAT="#,##0.00";
//定制日期格式
privatestaticStringDATE_FORMAT="m/d/yy";//"m/d/yyh:mm"
privateOutputStreamout=null;
privateWorkbookworkbook=null;
privateSheetsheet=null;
privateRowrow=null;
publicExcelWriter(){
}
publicExcelWriter(OutputStreamout){
this.out=out;
this.workbook=newSXSSFWorkbook(128);//POI3.8最新的API,解决问题的关键。
this.sheet=workbook.createSheet();
}
/**
*导出Excel文件
*@throwsIOException
*/
publicvoidexport()throwsFileNotFoundException,IOException{
try{
workbook.write(out);
out.flush();
out.close();
}catch(FileNotFoundExceptione){
thrownewIOException("生成导出Excel文件出错!",e);
}catch(IOExceptione){
thrownewIOException("写入Excel文件出错!",e);
}
}
/**
*增加一行
*@paramindex行号
*/
publicvoidcreateRow(intindex){
this.row=this.sheet.createRow(index);
}
/**
*获取单元格的值
*@paramindex列号
*/
publicStringgetCell(intindex){
Cellcell=this.row.getCell((short)index);
StringstrExcelCell="";
if(cell!=null){//addthiscondition
//judge
switch(cell.getCellType()){
caseCell.CELL_TYPE_FORMULA:
strExcelCell="FORMULA";
break;
caseCell.CELL_TYPE_NUMERIC:{
strExcelCell=String.valueOf(cell.getNumericCellValue());
}
break;
caseCell.CELL_TYPE_STRING:
strExcelCell=cell.getStringCellValue();
break;
caseCell.CELL_TYPE_BLANK:
strExcelCell="";
break;
default:
strExcelCell="";
break;
}
}
returnstrExcelCell;
}
/**
*设置单元格
*@paramindex列号
*@paramvalue单元格填充值
*/
publicvoidsetCell(intindex,intvalue){
Cellcell=this.row.createCell((short)index);
cell.setCellType(Cell.CELL_TYPE_NUMERIC);
cell.setCellValue(value);
}
/**
*设置单元格
*@paramindex列号
*@paramvalue单元格填充值
*/
publicvoidsetCell(intindex,doublevalue){
Cellcell=this.row.createCell((short)index);
cell.setCellType(Cell.CELL_TYPE_NUMERIC);
cell.setCellValue(value);
CellStylecellStyle=workbook.createCellStyle();//建立新的cell样式
DataFormatformat=workbook.createDataFormat();
cellStyle.setDataFormat(format.getFormat(NUMBER_FORMAT));//设置cell样式为定制的浮点数格式
cell.setCellStyle(cellStyle);//设置该cell浮点数的显示格式
}
/**
*设置单元格
*@paramindex列号
*@paramvalue单元格填充值
*/
publicvoidsetCell(intindex,Stringvalue){
Cellcell=this.row.createCell((short)index);
cell.setCellType(Cell.CELL_TYPE_STRING);
cell.setCellValue(value);
}
/**
*设置单元格
*@paramindex列号
*@paramvalue单元格填充值
*/
publicvoidsetCell(intindex,Calendarvalue){
Cellcell=this.row.createCell((short)index);
cell.setCellValue(value.getTime());
CellStylecellStyle=workbook.createCellStyle();//建立新的cell样式
DataFormatformat=workbook.createDataFormat();
cellStyle.setDataFormat(format.getFormat(DATE_FORMAT));//设置cell样式为定制的日期格式
cell.setCellStyle(cellStyle);//设置该cell日期的显示格式
}
publicstaticvoidmain(String[]args){
System.out.println("开始导出Excel文件");
Filef=newFile("C:\\qt.xls");
ExcelWritere=newExcelWriter();
try{
e=newExcelWriter(newFileOutputStream(f));
}catch(FileNotFoundExceptione1){
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(IOExceptionex){
System.out.println("导出Excel文件[失败]");
ex.printStackTrace();
}
}
}
这个只是个util。接着你就可以运用到你的工程中去了。下面是个测试类。
[html]viewplaincopyprint?
importjava.io.BufferedOutputStream;
importjava.io.FileNotFoundException;
importjava.io.FileOutputStream;
importjava.io.IOException;
publicclassTestExcelPOI{
publicstaticvoidmain(String[]args)throwsFileNotFoundException{
StringnewFilename="test_performance.xlsx";
introws=100000;
intcols=70;
BufferedOutputStreamout=newBufferedOutputStream(newFileOutputStream(newFileName));
ExcelWriterexcelWriter=newExcelWriter(out);
longstart=System.currentTimeMillis();
for(introwNum=0;rowNum<rows;rowNum++){
excelWriter.createRow(rowNum);
for(intcolNum=0;colNum<cols;colNum++){
Stringvalue=rowNum+"_"+colNum;//模拟数据
excelWriter.setCell(colNum,value);
}
}
try{
excelWriter.export();
System.out.println("导出Excel文件[成功]");
}catch(IOExceptionex){
System.out.println("导出Excel文件[失败]");
ex.printStackTrace();
}
longend=System.currentTimeMillis();
doubleseconds=(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,然后在合并,可惜效果也不佳。