`

批量导出大数据量到EXCEL

 
阅读更多
用到的jar包是 POI 3.8,注意导包的时候,那几个包都要导进去,下包就不用说了吧,官网上有。http://poi.apache.org/

接着是个工具类,无意中在网上发现了,感觉封装的不错,我就稍微修改了下,导出大数据量(30W数据,70列)到EXCEL2007,目前没有出现内存溢出问题。

[html] view plaincopyprint?
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。接着你就可以运用到你的工程中去了。下面是个测试类。

[html] view plaincopyprint?
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,然后在合并,可惜效果也不佳。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics