支持大批量数据导出EXCEL

原来程序用的poi的HSSF导出excel,后面数据量增多再导出报错(Invalid row number (65536) outside allowable range (0..65535)),然后改用XSSF后依然报错java.lang.OutOfMemoryError: Java heap space或者java.lang.OutOfMemoryError: GC overhead limit exceeded。百度了下,支持大批量数据导出用SXSSF,导出文件名是xlsx,支持导出百万条数据。

我是参考了这一篇博客https://blog.csdn.net/qq_33620899/article/details/78565384

下面是我自己的做法

controller:

    @ResponseBody
    @RequestMapping(value = "XXXXXXX")
    public ResponseEntity 方法名(String startDate,String endDate,Integer f_factory_id)throws Exception {
        Map map = Maps.newHashMap();
        if(StringUtils.isNotEmpty(startDate)){
            map.put("startDate",startDate);
        }
        if(StringUtils.isNotEmpty(endDate)){
            map.put("endDate",endDate);
        }
        if(f_factory_id !=null){
            map.put("f_factory_id",f_factory_id);
        }
        String now = DateFormatUtils.format(new Date(),"yyyyMMdd");
        HttpHeaders headers = new HttpHeaders();
        String downloadFielName = new String(("用户订单统计_"+now+".xlsx").getBytes("UTF-8"),"iso-8859-1");
        headers.setContentDispositionFormData("attachment", downloadFielName);
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        return new ResponseEntity(statisticsService.downloadUserOrderStatistics(map), headers, HttpStatus.CREATED);
    }

service:

public byte[] downloadUserOrderStatistics(Map param) throws Exception {
        List list = findUserOrderStatistics(param);
        if(CollectionUtils.isEmpty(list)){
            return null;
        }
        String[] titles = { "列名1", "列名2", "列名3","列名4", "列名5", "列名6", "列名7", "列名8", "列名9", "列名10", "列名11", "列名12", "列名13"};
        //return ExcelUtil.buildExcel(titles,list);//不适合大批量数据导出
        return ExcelUtil.buildExcelSXSS(titles,list);
    }

导出工具类:

public static byte[] buildExcelSXSS(Object[] columnTitles, List contents) throws Exception {
		XSSFWorkbook xssfWb = null;
		SXSSFWorkbook sxssfWorkbook = null;
		SXSSFSheet sxssSheet = null;
		ByteArrayOutputStream outputStream = null;
		byte[] bytes = null;
		try {
			outputStream = new ByteArrayOutputStream();
			xssfWb = new XSSFWorkbook();
			sxssfWorkbook = new SXSSFWorkbook(xssfWb, 1000);//默认读取1000行
			sxssSheet = (SXSSFSheet) sxssfWorkbook.createSheet("Sheet1");//分页名称
			
			//列头样式
			XSSFFont columnTitleFont = (XSSFFont) sxssfWorkbook.createFont();
			CellStyle columnTitleStyle = sxssfWorkbook.createCellStyle();
			columnTitleFont.setFontHeightInPoints((short) 14);
            columnTitleFont.setFontName("宋体");
            columnTitleFont.setColor(HSSFColor.BLACK.index);
            columnTitleFont.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
            columnTitleStyle.setFont(columnTitleFont);
			//先输出第一行注释
			int beginRow = 0;
            if (columnTitles.length > 1) {
                SXSSFRow row = (SXSSFRow) sxssSheet.createRow(beginRow);
                for (int i = 0; i < columnTitles.length; ++i) {
                    String value = (String)columnTitles[i];
                    //sxssSheet.setColumnWidth(beginRow,30*256);
                    SXSSFCell cell = (SXSSFCell) row.createCell(i);
                    cell.setCellValue(value);
                    cell.setCellStyle(columnTitleStyle);
                }
                beginRow++;
            }
            
            //内容样式
            XSSFFont contentfont = (XSSFFont) sxssfWorkbook.createFont();
            XSSFCellStyle contentStyle = (XSSFCellStyle) sxssfWorkbook.createCellStyle();
            contentfont.setFontHeightInPoints((short) 12);
            contentfont.setFontName("宋体");
            contentfont.setColor(HSSFColor.BLACK.index);
            contentfont.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
            contentStyle.setFont(contentfont);
            //这里要注意下,本来格式转换代码是写在下面循环里的,有残留,这里拿出来单独处理,也可以按照自己想法做
            XSSFDataFormat df = (XSSFDataFormat) sxssfWorkbook.createDataFormat();
            XSSFCellStyle contentStyleInteger = (XSSFCellStyle) sxssfWorkbook.createCellStyle();
            contentStyleInteger.setFont(contentfont);
            contentStyleInteger.setDataFormat(df.getFormat("#,#0"));//数据格式只显示整数
            XSSFCellStyle contentStyleDecimal = (XSSFCellStyle) sxssfWorkbook.createCellStyle();
            contentStyleDecimal.setFont(contentfont);
            contentStyleDecimal.setDataFormat(df.getFormat("#,##0.00"));//保留两位小数点
			
			//记录总数
			int listNum = contents.size();
			//查询数据库最大记录数
			int sourceMaxCache = 10000;
			//总共查询次数
			int findNum = 0;
			if (0 == (listNum % sourceMaxCache)){
				findNum = listNum / sourceMaxCache;
			}else {
				findNum = listNum / sourceMaxCache + 1;
			}
			//此次批量写入数据
			List listBatch = null;
			//已处理到第几位
			int nowNum = 0;
			for (int j = 0; j < findNum; j++){
				listBatch = new ArrayList<>();
				//把查询结果分批写入map list
				for (int a=0;a

导出速度也还行,9W+条数据大概20多秒

你可能感兴趣的:(导出Excel)