EXCEL 下载

220 阅读3分钟

POI操作EXCEL对象

HSSF:操作Excel 97(.xls)格式 
XSSF:操作Excel 2007 OOXML (.xlsx)格式,操作EXCEL内存占用高于HSSF 
SXSSF:从POI3.8 beta3开始支持,基于XSSF,低内存占用。

使用POI的HSSF对象,生成Excel 97(.xls)格式,生成的EXCEL不经过压缩直接导出。 
线上问题:负载服务器转发请求到应用服务器阻塞,以及内存溢出 。 
如果系统存在大数据量报表导出,则考虑使用POI的SXSSF进行EXCEL操作。

HSSF生成的Excel 97(.xls)格式本身就有每个sheet页不能超过65536条的限制。 
XSSF生成Excel 2007 OOXML (.xlsx)格式,条数增加了,但是导出过程中,内存占用率却高于HSSF. 
SXSSF是自3.8-beta3版本后,基于XSSF提供的低内存占用的操作EXCEL对象。其原理是可以设置或者手动将内存中的EXCEL行写到硬盘中,这样内存中只保存了少量的EXCEL行进行操作。

EXCEL的压缩率特别高,能达到80%,12M的文件压缩后才2M左右。 如果未经过压缩、不仅会占用用户带宽,且会导致负载服务器(apache)和应用服务器之间,长时间占用连接(二进制流转发),导致负载服务器请求阻塞,不能提供服务。

一定要注意文件流的关闭
防止前台(页面)连续触发导出EXCEL

一、导出Excel 97(.xls)格式 ,少量数据, 65535 条数据以下

    //存储最大列宽,宽度自适应需要使用  
    Map<Integer,Integer> maxWidth = new HashMap<Integer,Integer>();
    
    // 声明一个工作薄
    HSSFWorkbook wb=new HSSFWorkbook();
    // 生成一个(带标题)表格
    HSSFSheet sheet = wb.createSheet();
    //第一行
    HSSFRow row=sheet.createRow(0);
    //循环设置第一行的标题
    for(int i=0;i<list.size();i++){
    	String cm = list.get(i).getName();
    	//获取列
    	HSSFCell cell = row.createCell(i);
    	//设置内容
    	cell.setCellValue(cm);
    	maxWidth.put(i,cell.getStringCellValue().getBytes().length  * 256 + 200);
    }
    //填充数据
    HSSFRow row = null;
    int index=1;
    for(int i=0;i<总条数.size();i++){
        row = sheet.createRow(index++);
        for(int j=0;j<数据.size();j++){
            HSSFCell cel = row.createCell(j);
            cel.setCellValue("值");
            //取列的最大宽度
            int length = cel.getStringCellValue().getBytes().length  * 256 + 200;  
            if ( maxWidth.containsKey(c) && maxWidth.get(c)<length ){  
                maxWidth.put(c,length);
            }  
        }
    }
    //设置列宽
    for(int i=0;i<列总数.size();i++){
    	sheet.setColumnWidth(i, maxWidth.get(i));
    }

二、导出Excel 2007 OOXML (.xlsx)格式 1024*1024 = 1048576 条数据

    //存储最大列宽,宽度自适应需要使用  
    Map<Integer,Integer> maxWidth = new HashMap<Integer,Integer>();
    
    // 声明一个工作薄
    Workbook wb=new SXSSFWorkbook();
    // 生成一个(带标题)表格
    Sheet sheet = wb.createSheet();
    //第一行
    Row row = sheet.createRow(0);
    //循环设置第一行的标题
    for(int i=0;i<list.size();i++){
    	String cm = list.get(i).getName();
    	//获取列
    	Cell cell = row.createCell(i);
    	//设置内容
    	cell.setCellValue(cm);
    	maxWidth.put(i,cell.getStringCellValue().getBytes().length  * 256 + 200);
    }
    //填充数据
    Row row = null;
    int index=1;
    for(int i=0;i<总条数.size();i++){
        row = sheet.createRow(index++);
        for(int j=0;j<数据.size();j++){
            Cell cel = row.createCell(j);
            cel.setCellValue("值");
            //取列的最大宽度
            int length = cel.getStringCellValue().getBytes().length  * 256 + 200;  
            if ( maxWidth.containsKey(c) && maxWidth.get(c)<length ){  
                maxWidth.put(c,length);
            }  
        }
    }
    //设置列宽
    for(int i=0;i<列总数.size();i++){
    	sheet.setColumnWidth(i, maxWidth.get(i));
    }