java POI导出excel性能优化
项目场景:
导出40万以上的数据到xlsx
问题描述:
实施地出现导出40万数据到excel中时,CPU占不超过100%,时间超过半个小时,系统中其他功能模块卡顿
@EcpGetMapping("/exportResultDetail")public void exportResultDetail(final HttpServletRequest req, final HttpServletResponse resp, @RequestParam final String operParams) {byte[] exportBytes = null;ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();try {JSONObject jsonObj = JSONObject.parseObject(operParams);String fileName = String.valueOf(jsonObj.get("fileName"));String fileType = String.valueOf(jsonObj.get("fileType"));String compId = String.valueOf(jsonObj.get("compId"));String modelId = String.valueOf(jsonObj.get("modelId"));List<Map> colList = this.mainResultService.findColListByModelId(compId, modelId);String queryParamStr = String.valueOf(jsonObj.get("queryParam"));Map queryParam = JSONUtil.fromJsonString(queryParamStr, Map.class);
// fileName = new String(fileName.getBytes("iso8859-1"),"utf8");Map<String, Object> queryResult = this.tAmModelMainResultService.queryDetailList(queryParam);List<Map> list = (List<Map>) queryResult.get("data");final Workbook exportWorkbook = AmExcelHelpUtil.createWorkbook(fileType);exportWorkbook.createSheet(fileName);final CellStyle headCellStyle = exportWorkbook.createCellStyle();final CellStyle contentCellStyle = exportWorkbook.createCellStyle();final CellStyle contentCenterCellStyle = exportWorkbook.createCellStyle();final CellStyle contentRightCellStyle = exportWorkbook.createCellStyle();final Font headCellFont = exportWorkbook.createFont();final Font contentFont = exportWorkbook.createFont();final Sheet manuSheetNew = exportWorkbook.getSheetAt(0);manuSheetNew.setDefaultRowHeightInPoints((short) 25);manuSheetNew.setDefaultColumnWidth(25);final Row headRow = manuSheetNew.createRow(0); // 标题行int colCount = colList.size();for (int j = 0; j < colCount; j++) {final Cell cell = headRow.createCell(j);headCellStyle.setAlignment(CellStyle.ALIGN_CENTER);headCellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);headCellStyle.setWrapText(true);headCellFont.setFontHeightInPoints((short)10);headCellFont.setFontName("微软雅黑");headCellFont.setBoldweight(Font.BOLDWEIGHT_BOLD);headCellStyle.setFont(headCellFont);headCellStyle.setBorderBottom(CellStyle.BORDER_THIN);headCellStyle.setBorderLeft(CellStyle.BORDER_THIN);headCellStyle.setBorderRight(CellStyle.BORDER_THIN);headCellStyle.setBorderTop(CellStyle.BORDER_THIN);headCellStyle.setFillForegroundColor(HSSFColor.LIGHT_CORNFLOWER_BLUE.index);headCellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);cell.setCellStyle(headCellStyle);Map colMap = colList.get(j);String colCnName = String.valueOf(colMap.get("colcnname"));excelHelpUtil.setCellValue(fileType, manuSheetNew, 0, j, colCnName);}if (list != null && list.size() > 0) {int indx = 1;for (Map dataMap : list) {if (dataMap == null) {continue;}final Row row = manuSheetNew.createRow(indx);row.setHeightInPoints((short) 25);for (int j = 0; j < colCount; j++) {final Cell cell = row.createCell(j);Map colMap = colList.get(j);String colEnName = String.valueOf(colMap.get("colenname")).toLowerCase();String dataType = String.valueOf(colMap.get("coldatatype"));if ("1,2".contains(dataType)) {contentCenterCellStyle.setAlignment(CellStyle.ALIGN_CENTER);contentCenterCellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);contentCenterCellStyle.setWrapText(true);contentFont.setFontHeightInPoints((short) 10);contentFont.setFontName("微软雅黑");contentCenterCellStyle.setFont(contentFont);contentCenterCellStyle.setBorderBottom(CellStyle.BORDER_THIN);contentCenterCellStyle.setBorderLeft(CellStyle.BORDER_THIN);contentCenterCellStyle.setBorderRight(CellStyle.BORDER_THIN);contentCenterCellStyle.setBorderTop(CellStyle.BORDER_THIN);cell.setCellStyle(contentCenterCellStyle);} else if ("3".equals(dataType)) {contentRightCellStyle.setAlignment(CellStyle.ALIGN_RIGHT);contentRightCellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);contentRightCellStyle.setWrapText(true);contentFont.setFontHeightInPoints((short) 10);contentFont.setFontName("微软雅黑");contentRightCellStyle.setFont(contentFont);contentRightCellStyle.setBorderBottom(CellStyle.BORDER_THIN);contentRightCellStyle.setBorderLeft(CellStyle.BORDER_THIN);contentRightCellStyle.setBorderRight(CellStyle.BORDER_THIN);contentRightCellStyle.setBorderTop(CellStyle.BORDER_THIN);cell.setCellStyle(contentRightCellStyle);} else {contentCellStyle.setAlignment(CellStyle.ALIGN_LEFT);contentCellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);contentCellStyle.setWrapText(true);contentFont.setFontHeightInPoints((short) 10);contentFont.setFontName("微软雅黑");contentCellStyle.setFont(contentFont);contentCellStyle.setBorderBottom(CellStyle.BORDER_THIN);contentCellStyle.setBorderLeft(CellStyle.BORDER_THIN);contentCellStyle.setBorderRight(CellStyle.BORDER_THIN);contentCellStyle.setBorderTop(CellStyle.BORDER_THIN);cell.setCellStyle(contentCellStyle);}excelHelpUtil.setCellValue(fileType, manuSheetNew, indx, j, String.valueOf(dataMap.get(colEnName)));}indx++;}}exportWorkbook.write(byteArrayOut);exportBytes = byteArrayOut.toByteArray();resp.setStatus(200);resp.setContentType("application/x-download;charset=utf8");resp.addHeader("Content-Disposition", String.format("attachment; filename=\"%s\"",URLEncoder.encode(fileName + "." + fileType, "UTF-8")));resp.getOutputStream().write(exportBytes);} catch (IOException e) {e.printStackTrace();}}
原因分析:
- 大数据量导出应该使用poi 3.8以上提供的类SXSSFWorkbook,2007版 XSSFWorkbook不适用于数据量较大的数据导出。
- 创建样式对象时,应重复使用,不要每次填充cell时都新建一个样式对象。
解决方案:
/*** * @param req* @param resp* @param operParams*/@EcpGetMapping("/exportResultDetailForExcel")public void exportResultDetailForExcel(final HttpServletRequest req, final HttpServletResponse resp, @RequestParam final String operParams) {byte[] exportBytes = null;ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();SXSSFWorkbook exportWorkbook = null;try {JSONObject jsonObj = JSONObject.parseObject(operParams);String fileName = String.valueOf(jsonObj.get("fileName"));String fileType = String.valueOf(jsonObj.get("fileType"));String compId = String.valueOf(jsonObj.get("compId"));String modelId = String.valueOf(jsonObj.get("modelId"));List<Map> colList = this.mainResultService.findColListByModelId(compId, modelId);String queryParamStr = String.valueOf(jsonObj.get("queryParam"));Map queryParam = JSONUtil.fromJsonString(queryParamStr, Map.class);Map<String, Object> queryResult = this.tAmModelMainResultService.queryDetailList(queryParam);List<Map> list = (List<Map>) queryResult.get("data");exportWorkbook = new SXSSFWorkbook(2000);exportWorkbook.setCompressTempFiles(false);exportWorkbook.createSheet(fileName);final CellStyle headCellStyle = exportWorkbook.createCellStyle();final CellStyle contentCenterCellStyle = exportWorkbook.createCellStyle();final Font headCellFont = exportWorkbook.createFont();headCellStyle.setAlignment(CellStyle.ALIGN_CENTER);headCellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);headCellStyle.setWrapText(true);headCellFont.setFontHeightInPoints((short)10);headCellFont.setFontName("微软雅黑");headCellFont.setBoldweight(Font.BOLDWEIGHT_BOLD);headCellStyle.setFont(headCellFont);headCellStyle.setBorderBottom(CellStyle.BORDER_THIN);headCellStyle.setBorderLeft(CellStyle.BORDER_THIN);headCellStyle.setBorderRight(CellStyle.BORDER_THIN);headCellStyle.setBorderTop(CellStyle.BORDER_THIN);headCellStyle.setFillForegroundColor(HSSFColor.LIGHT_CORNFLOWER_BLUE.index);headCellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);final Font contentFont = exportWorkbook.createFont();//居中contentFont.setFontHeightInPoints((short) 10);contentFont.setFontName("微软雅黑");contentCenterCellStyle.setAlignment(CellStyle.ALIGN_CENTER);contentCenterCellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);contentCenterCellStyle.setWrapText(true);contentCenterCellStyle.setFont(contentFont);contentCenterCellStyle.setBorderBottom(CellStyle.BORDER_THIN);contentCenterCellStyle.setBorderLeft(CellStyle.BORDER_THIN);contentCenterCellStyle.setBorderRight(CellStyle.BORDER_THIN);contentCenterCellStyle.setBorderTop(CellStyle.BORDER_THIN);//居右final CellStyle contentRightCellStyle = exportWorkbook.createCellStyle();contentRightCellStyle.setAlignment(CellStyle.ALIGN_RIGHT);contentRightCellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);contentRightCellStyle.setWrapText(true);contentRightCellStyle.setBorderBottom(CellStyle.BORDER_THIN);contentRightCellStyle.setBorderLeft(CellStyle.BORDER_THIN);contentRightCellStyle.setBorderRight(CellStyle.BORDER_THIN);contentRightCellStyle.setBorderTop(CellStyle.BORDER_THIN);contentFont.setFontHeightInPoints((short) 10);contentFont.setFontName("微软雅黑");contentRightCellStyle.setFont(contentFont);//居左final CellStyle contentCellStyle = exportWorkbook.createCellStyle();contentCellStyle.setAlignment(CellStyle.ALIGN_LEFT);contentCellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);contentCellStyle.setWrapText(true);contentFont.setFontHeightInPoints((short) 10);contentFont.setFontName("微软雅黑");contentCellStyle.setFont(contentFont);contentCellStyle.setBorderBottom(CellStyle.BORDER_THIN);contentCellStyle.setBorderLeft(CellStyle.BORDER_THIN);contentCellStyle.setBorderRight(CellStyle.BORDER_THIN);contentCellStyle.setBorderTop(CellStyle.BORDER_THIN);final Sheet manuSheetNew = exportWorkbook.getSheetAt(0);manuSheetNew.setDefaultRowHeightInPoints((short) 25);manuSheetNew.setDefaultColumnWidth(25);final Row headRow = manuSheetNew.createRow(0); // 标题行int colCount = colList.size();for (int j = 0; j < colCount; j++) {final Cell cell = headRow.createCell(j); cell.setCellStyle(headCellStyle);Map colMap = colList.get(j);String colCnName = String.valueOf(colMap.get("colcnname"));excelHelpUtil.setSXSSFCellValue(fileType, manuSheetNew, 0, j, colCnName);}if (list != null && list.size() > 0) {int indx = 1;for (Map dataMap : list) {if (dataMap == null) {continue;}final Row row = manuSheetNew.createRow(indx);row.setHeightInPoints((short) 25);for (int j = 0; j < colCount; j++) {final Cell cell = row.createCell(j);Map colMap = colList.get(j);String colEnName = String.valueOf(colMap.get("colenname")).toLowerCase();String dataType = String.valueOf(colMap.get("coldatatype"));if ("1,2".contains(dataType)) { cell.setCellStyle(contentCenterCellStyle);} else if ("3".equals(dataType)) { cell.setCellStyle(contentRightCellStyle);} else { cell.setCellStyle(contentCellStyle);}excelHelpUtil.setSXSSFCellValue(fileType, manuSheetNew, indx, j, String.valueOf(dataMap.get(colEnName)));}indx++;}}exportWorkbook.write(byteArrayOut);exportBytes = byteArrayOut.toByteArray();resp.setStatus(200);resp.setContentType("application/x-download;charset=utf8");resp.addHeader("Content-Disposition", String.format("attachment; filename=\"%s\"",URLEncoder.encode(fileName + "." + fileType, "UTF-8")));resp.getOutputStream().write(exportBytes);} catch (IOException e) {e.printStackTrace();} finally{if (exportWorkbook != null) {try {//删除磁盘上的文件deleteSXSSFTempFiles(exportWorkbook);} catch (NoSuchFieldException | IllegalAccessException e) {e.printStackTrace();}}}}/*** Returns a private attribute of a class* @param containingClass The class that contains the private attribute to retrieve* @param fieldToGet The name of the attribute to get* @return The private attribute* @throws NoSuchFieldException* @throws IllegalAccessException */public static Object getPrivateAttribute(final Object containingClass, final String fieldToGet) throws NoSuchFieldException, IllegalAccessException {//get the field of the containingClass instanceField declaredField = containingClass.getClass().getDeclaredField(fieldToGet);//set it as accessibledeclaredField.setAccessible(true);//access itObject get = declaredField.get(containingClass);//return it!return get;}/*** 删除缓存文件 Deletes all temporary files of the SXSSFWorkbook instance.* @param workbook* @throws NoSuchFieldException* @throws IllegalAccessException */public static void deleteSXSSFTempFiles(final SXSSFWorkbook workbook) throws NoSuchFieldException, IllegalAccessException {int numberOfSheets = workbook.getNumberOfSheets();//iterate through all sheets (each sheet as a temp file)for (int i = 0; i < numberOfSheets; i++) {Sheet sheetAt = workbook.getSheetAt(i);//delete only if the sheet is written by streamif (sheetAt instanceof SXSSFSheet) {SheetDataWriter sdw = (SheetDataWriter) getPrivateAttribute(sheetAt,"_writer");//如果exportWorkbook.setCompressTempFiles(true);//下一行代码就会报错File f = (File) getPrivateAttribute(sdw,"_fd");try {f.delete();} catch (Exception ex) {//could not delete the file}}}}
说明:由于poi 3.8 没有 dispose()方法,所以需要写清除硬盘上存的文件,poi 3.8以上就可以直接使用。
exportWorkbook = new SXSSFWorkbook(2000);
就是将超过2000条的数据存入到电脑磁盘上,2000以内的数据放入缓存中,这样就可以减少内存的占用。创建样式的话,不需要放在for循环中,这样就解决问题了,36万的数据只需要10几秒就导出完成,提高了导出的性能。
java POI导出excel性能优化相关推荐
- java poi 导出excel不能超过65536行
java poi 导出excel不能超过65536行 报这个异常 Exception in thread "main" java.lang.IllegalArgumentExcep ...
- java poi导出Excel表格超大数据量解决方案
Java实现导出excel表格功能,大部分都会使用apache poi,apache poi API 地址 POI之前的版本不支持大数据量处理,如果数据过多则经常报OOM错误,有时候调整JVM大小效果 ...
- Java POI 导出EXCEL经典实现 Java导出Excel弹出下载框
原文转载:http://blog.csdn.net/evangel_z/article/details/7332535 目录(?)[+] 在web开发中,有一个经典的功能,就是数据的导入导出.特别是数 ...
- Java POI 导出EXCEL经典实现 Java导出Excel
转自http://blog.csdn.net/evangel_z/article/details/7332535 在web开发中,有一个经典的功能,就是数据的导入导出.特别是数据的导出,在生产管理或者 ...
- Java POI导出Excel
版权声明:本文为博主原创文章,未经博主允许不得转载. 在软件开发工作当中,导出Excel表格是比较常见的,下面我为大家分享一下POI导出Excel的一些方法. 1.引用poi.jar包 < ...
- JAVA POI 导出EXCEL时,EXCEL模板中的公式无效问题
JAVA POI 出力EXCEL时,EXCEL模板中的公式无效问题 工作中遇到一个问题. EXCEL模板有两个sheet,画面内容要导出到第二个sheet中,第一个sheet设置公式,读取第二个she ...
- java poi 导出excel 数字有问题
在用poi导出excel时 导出的数字为文本格式(左上角有绿色三角) 原因: cell.setCellType(Cell.CELL_TYPE_NUMERIC); cell.setCellValue( ...
- JAVA POI导出EXCEL设置自定义样式(线框加粗,合并指定行,合计求和,冻结行)
前面部分是当时查询的记录: 实现Excel文件单元格合并.冻结和文件导出 Workbook wb = new HSSFWorkbook();Sheet sheet = wb.createSheet(& ...
- Java POI导出Excel时,合并单元格没有边框的问题
今天用POI导出Excel的时候,发现导出的单元格确少边框,最后发现有2个方案可以解决. 方案一 CellRangeAddress的4个参数分别表示:起始行号,终止行号, 起始列号,终止列号 // 使 ...
- java poi 导出excel 速度慢_java POI技术之导出数据优化(15万条数据1分多钟)
专针对导出excel2007 ,用到poi3.9的jar package com.cares.ynt.util; import java.io.File; import java.io.FileOut ...
最新文章
- 【Vegas原创】解决System.Web.Extensions版本冲突方法
- LeetCode Find All Numbers Disappeared in an Array
- 开源APM技术选型与实战
- css3新特性总结(视觉表现方面)
- AESNI/XData勒索病毒来袭 目前主要在乌克兰传播 它居然还能使用硬件加速加密过程...
- 在 Apache Spark 中利用 HyperLogLog 函数实现高级分析
- CentOS 7系统上部署Apache+PHP+MariaDB+xcache使用rpm,php module
- 光线跟踪的几种常见求交运算
- 对话哈佛大学教授Lukin:量子计算将在我们有生之年普及!
- 世界各国简称 电话区号JSON数据
- python自动化plc_PYTHON – 让“Monty 语言”进入自动化行业:第 4 部分
- 庆祝JavaCard技术领导SmartCard技术超过五年
- Flask项目实战——6—(前台用户模型、前台登录注册、图形验证码、手机短信验证码、添加表单验证短信验证码请求)
- 读书笔记:Python编程——从入门到实践
- hadoop配置、运行错误总结一
- 我的Android说
- Visual Studio 2019解决右侧工具栏消失
- 网络安全学习记录-9
- osgEarth示例分析——osgearth_imageoverlay
- Java-null(对空值得处理)