批量导出大数据量到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,然后在合并,可惜效果也不佳。

相关推荐