POI和EasyExcel
- IT业界
- 2025-09-07 20:48:02

前言 将表格信息导出为Excel表格(导出数)将Excel表格信息录入到数据库(导入数据)
操作Excel目前比较流行的就是 Apache POI 和阿里巴巴的 EasyExcel
Apache POIApache POI 官网: poi.apache.org/
HSSF:Excel97-2003版本,扩展名为.xls。一个sheet最大行数65536,最大列数256。XSSF:Excel2007版本开始,扩展名为.xlsx。一个sheet最大行数1048576,最大列数16384。SXSSF:是在XSSF基础上,POI3.8版本开始提供的支持低内存占用的操作方式,扩展名为.xlsx。Excel版本兼容性是向下兼容。
03版本和07版的Excel表的生成
<!--xls(03版本)--> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.9</version> </dependency> <!--xlsx(07版本)--> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.9</version> </dependency>代码
@Override @CrossOrigin public void testEasyExcel(Map<String, Object> map, HttpServletResponse response) throws IOException { // var sheetName = "工作表名" // var headList = ["表头1", "表头2"] // var filedList = ["字段名1", "字段名2"] // var dataList = [{字段名1: "2914"}, {字段名2: "2935"}, {字段名3: "2937"}] String sheetName = map.get("sheetName").toString(); List<String> headList = (List)map.get("headList"); List<String> filedList = (List)map.get("filedList"); List<Map> dataList = (List)map.get("dataList"); // 创建一个03版本的工作簿 Workbook workbook = new HSSFWorkbook(); // 创建一个07版本的工作簿 // Workbook workbook = new XSSFWorkbook(); // // Workbook workbook = new SXSSFWorkbook(); // 创建一个工作表,指定表名 Sheet sheet = workbook.createSheet(sheetName); // 创建一个行 Row row = sheet.createRow(0); // 设置行高 row.setHeight((short)450); // 设置样式 HSSFCellStyle cellStyle = (HSSFCellStyle)workbook.createCellStyle(); // XSSFCellStyle cellStyle = (XSSFCellStyle) workbook.createCellStyle(); // 设置背景颜色 cellStyle.setFillBackgroundColor(IndexedColors.SEA_GREEN.getIndex()); // 设置居中 // cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 设置字体 HSSFFont font = (HSSFFont)workbook.createFont(); // XSSFFont font = (XSSFFont)workbook.createFont(); font.setFontName("宋体"); font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); font.setFontHeightInPoints((short)12); cellStyle.setFont(font); // 写入表头 for (int i = 0; i < headList.size(); i++) { row.createCell(i).setCellValue(headList.get(i)); row.getCell(i).setCellStyle(cellStyle); } // 写入字段名和写入数据 for (int i = 0; i < dataList.size(); i++) { row = sheet.createRow(i + 1); row.setHeight((short)450); Map<String, String> datamap = dataList.get(i); for (int j = 0; j < filedList.size(); j++) { String value = String.valueOf(datamap.get(filedList.get(j))); if (value != null && !"null".equals(value)) { row.createCell(j).setCellValue(value); } } } // 文件扩展名 response.setContentType("application/vnd.ms-excel;charset=utf-8"); OutputStream os = response.getOutputStream(); // 输出 workbook.write(os); // 刷新 os.flush(); // 关闭 os.close(); // 清除临时文件 // ((SXSSFWorkbook)workbook).dispose(); }03版本和07版的Excel表的读取
@Override @CrossOrigin public void testEasyExcel(Map<String, Object> map, HttpServletResponse response) throws IOException { // 获取文件流 03 xls 07 xlsx FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Desktop\\工号批量导入模板.xls"); // 读取excel Workbook workbook = new HSSFWorkbook(fileInputStream); // 拿到工作表 Sheet sheet = workbook.getSheetAt(0); // 获取标题行内容 Row rowTitle = sheet.getRow(1); if (rowTitle != null) { // 获取这行有多少列 int cellCount = rowTitle.getPhysicalNumberOfCells(); // 循环得到这一行的所有数据 for (int cellNum = 0; cellNum < cellCount; cellNum++) { Cell cell = rowTitle.getCell(cellNum); if (cell != null) { int cellType = cell.getCellType(); // 这里标题行数据的类型全部为字符串 String stringCellValue = cell.getStringCellValue(); System.out.print(stringCellValue + " | "); } } System.out.println(); } // 获取表中的内容,即获取除了第一行的内容,取表中总共有多少行 int physicalNumberOfRows = sheet.getPhysicalNumberOfRows(); // 从第二行开始循环,即获取除了第一行的内容 for (int rowNum = 2; rowNum < physicalNumberOfRows; rowNum++) { Row rowData = sheet.getRow(rowNum); if (rowData != null) { // 根据标题行获取多少列 int cellCount = rowTitle.getPhysicalNumberOfCells(); // 循环得到这一行的所有数据 for (int cellNum = 0; cellNum < cellCount; cellNum++) { Cell cell = rowData.getCell(cellNum); if (cell != null) { int cellType = cell.getCellType(); String cellValue = ""; // 匹配列的数据类型 switch (cellType) { // 字符串 case HSSFCell.CELL_TYPE_STRING: cellValue = cell.getStringCellValue(); break; // 布尔值 case HSSFCell.CELL_TYPE_BOOLEAN: cellValue = String.valueOf(cell.getBooleanCellValue()); break; // 空 case HSSFCell.CELL_TYPE_BLANK: break; // 数字(数字又分为日期和普通数字) case HSSFCell.CELL_TYPE_NUMERIC: // 如果为日期 if (HSSFDateUtil.isCellDateFormatted(cell)) { Date date = cell.getDateCellValue(); cellValue = new DateTime(date).toString("yyyy-MM-dd"); } else { // 不是日期格式的话,需要防止数字过长,转换为字符串输出 cell.setCellType(HSSFCell.CELL_TYPE_STRING); cellValue = cell.toString(); } break; // 错误的数据类型 case HSSFCell.CELL_TYPE_ERROR: break; } System.out.print(cellValue + " | "); } } System.out.println(); } } fileInputStream.close(); }通过 Blob 下载文件
前端的各种后台管理系统中,往往都会存在大量数据的展示,分析等,一般这种项目都会有数据导出功能,在开发中,一般都是后端返回Blob数据类型,也就是一个二进制对象,那么本篇文章就是讲解前端拿到Blob数据后该怎么处理。
这里简单说一下Blob,全称Binary large Object,二进制大对象(BLOB)是一种可以存储二进制对象或数据的数据类型。
前端中Blob对象的构造函数语法:
new Blob(array, options)参数 array 是一个数据序列即数组,可以是任意格式的值,例如,任意数量的字符串,Blobs 以及 ArrayBuffers。 参数 options 用于指定将要放入Blob中的数据的类型(MIME)
在封装请求的时候一定要记得加上responseType。 /** * 导出exportExcel * @param data */ public static exportExcel(data) { return axios({ url: ``, method: 'get', params: data, responseType: "blob"//定义好返回的数据类型 }); } 拿到Blob数据类型转化为文件并下载。 /** * 导出文件下载方法 * @param data 这个参数就是从接口返回的Blob二进制文件流 */ const exportFile= (data) => { const blob = new Blob([data], {type: "application/vnd.ms-excel;charset=utf-8"}); const fileName = "文件名" + new Date().getTime() + ".xls";//我这里是文件名加上时间,可以根据自己需求来 const elink = document.createElement("a"); // 创建a标签 elink.download = fileName; // 为a标签添加download属性 //命名下载名称 elink.style.display = "none"; elink.href = URL.createObjectURL(blob); document.body.appendChild(elink); elink.click(); // 点击下载 URL.revokeObjectURL(elink.href); // 释放URL 对象 document.body.removeChild(elink); // 释放标签 } EasyExceleasyExcel 官网: easyexcel.opensource.alibaba /
EasyExcel 是阿里巴巴开源的一个excel处理框架、以使用简单、节省内存著称,EasyExcel 能大大减少占用内存的主要原因是在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析。
下图是EasyExcel和POI在解析Excel时的对比图
代码
@Override @CrossOrigin public void testEasyExcel(Map<String, Object> map, HttpServletResponse response) throws IOException { String fileName = "C:\\Users\\13992\\Desktop\\EasyTest.xlsx"; // 这里需要指定写用哪个class去写,然后写到第一个sheet,名字为模板然后文件流会自动关闭 // 如果这里想使用03 则 传入excelType参数即可 List<Map> list = (List<Map>) map.get("dataList"); List<DemoData> demoList = ListUtils.newArrayList(); for(int i=0;i<list.size();i++){ DemoData data = new DemoData(); data.setStaffCode(list.get(i).get("staffCode").toString()); data.setStaffName(list.get(i).get("staffName").toString()); demoList.add(data); } EasyExcel.write(fileName, DemoData.class).sheet(map.get("sheetName").toString())// 工作表名 .doWrite(demoList); } 结论POI存在的问题:非常的消耗内存,EasyExcel 遇到再大的excel都不会出现内存溢出的问题,能够将一个原本3M的excel文件,POI来操作将会占用内存100M,使用EasyExcel降低到几KB,使用起来更加简单。而easyExcel能大大减少占用内存的主要原因是在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析。
POI和EasyExcel由讯客互联IT业界栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“POI和EasyExcel”
上一篇
AltiumDesigner23原理图编译NetXXXhas
下一篇
JAVA集合