360做的网站,网站开发工程师职业,郑州达云通网站建设公司,网站提交收录软件一、介绍在平时的业务系统开发中#xff0c;少不了需要用到导出、导入excel功能#xff0c;今天我们就一起来总结一下#xff0c;如果你正为此需求感到困惑#xff0c;那么阅读完本文#xff0c;你一定会有所收获#xff01;二、poi大概在很久很久以前#xff0c;微软的…
一、介绍在平时的业务系统开发中少不了需要用到导出、导入excel功能今天我们就一起来总结一下如果你正为此需求感到困惑那么阅读完本文你一定会有所收获二、poi大概在很久很久以前微软的电子表格软件 Excel 以操作简单、存储数据直观方便还支持打印报表在诞生之初可谓深得办公室里的白领青睐极大的提升了工作的效率不久之后便成了办公室里的必备工具。随着更多的新语言的崛起例如我们所熟悉的 java后来便有一些团队开始开发一套能与 Excel 软件无缝切换的操作工具这其中就有我们所熟悉的 apache 的 poi其前身是 Jakarta 的 POI Project项目之后将其开源给 apache 基金会当然在java生态体系里面能与Excel无缝衔接的第三方工具还有很多因为 apache poi 在业界使用的最广泛因此其他的工具不做过多介绍话不多说直接开撸2.1、首先引入apache poi的依赖dependencies!--xls(03)--dependencygroupIdorg.apache.poi/groupIdartifactIdpoi/artifactIdversion4.1.2/version/dependency!--xlsx(07)--dependencygroupIdorg.apache.poi/groupIdartifactIdpoi-ooxml/artifactIdversion4.1.2/version/dependency!--时间格式化工具--dependencygroupIdjoda-time/groupIdartifactIdjoda-time/artifactIdversion2.10.6/version/dependency
/dependencies
2.2、导出excel导出操作即使用 Java 写出数据到 Excel 中常见场景是将页面上的数据导出这些数据可能是财务数据也可能是商品数据生成 Excel 后返回给用户下载文件。在 poi 工具库中导出 api 可以分三种方式HSSF方式这种方式导出的文件格式为office 2003专用格式即.xls优点是导出数据速度快但是最多65536行数据XSSF方式这种方式导出的文件格式为office 2007专用格式即.xlsx优点是导出的数据不受行数限制缺点导出速度慢SXSSF方式SXSSF 是 XSSF API的兼容流式扩展主要解决当使用 XSSF 方式导出大数据量时内存溢出的问题支持导出大批量的excel数据2.2.1、HSSF方式导出HSSF方式最多只支持65536条数据导出超过这个条数会报错public class ExcelWrite2003Test {public static String PATH /Users/hello/Desktop/;public static void main(String[] args) throws Exception {//时间long begin System.currentTimeMillis();//创建一个工作簿Workbook workbook new HSSFWorkbook();//创建表Sheet sheet workbook.createSheet();//写入数据for (int rowNumber 0; rowNumber 65536; rowNumber) {//创建行Row row sheet.createRow(rowNumber);for (int cellNumber 0; cellNumber 10; cellNumber) {//创建列Cell cell row.createCell(cellNumber);cell.setCellValue(cellNumber);}}System.out.println(over);FileOutputStream fileOutputStream new FileOutputStream(PATH 用户信息表2003BigData.xls);workbook.write(fileOutputStream);fileOutputStream.close();long end System.currentTimeMillis();System.out.println((double) (end - begin) / 1000);//4.29s}
}
2.2.2、XSSF方式导出XSSF方式支持大批量数据导出所有的数据先写入内存再导出容易出现内存溢出public class ExcelWrite2007Test {public static String PATH /Users/hello/Desktop/;public static void main(String[] args) throws Exception {//时间long begin System.currentTimeMillis();//创建一个工作簿Workbook workbook new XSSFWorkbook();//创建表Sheet sheet workbook.createSheet();//写入数据for (int rowNumber 0; rowNumber 65537; rowNumber) {Row row sheet.createRow(rowNumber);for (int cellNumber 0; cellNumber 10; cellNumber) {Cell cell row.createCell(cellNumber);cell.setCellValue(cellNumber);}}System.out.println(over);FileOutputStream fileOutputStream new FileOutputStream(PATH 用户信息表2007BigData.xlsx);workbook.write(fileOutputStream);fileOutputStream.close();long end System.currentTimeMillis();System.out.println((double) (end - begin) / 1000);//15.87s}
}
2.2.3、SXSSF方式导出SXSSF方式是XSSF方式的一种延伸主要特性是低内存导出的时候先将数据写入磁盘再导出避免报内存不足导致程序运行异常缺点是运行很慢public class ExcelWriteSXSSFTest {public static String PATH /Users/hello/Desktop/;public static void main(String[] args) throws Exception {//时间long begin System.currentTimeMillis();//创建一个工作簿Workbook workbook new SXSSFWorkbook();//创建表Sheet sheet workbook.createSheet();//写入数据for (int rowNumber 0; rowNumber 100000; rowNumber) {Row row sheet.createRow(rowNumber);for (int cellNumber 0; cellNumber 10; cellNumber) {Cell cell row.createCell(cellNumber);cell.setCellValue(cellNumber);}}System.out.println(over);FileOutputStream fileOutputStream new FileOutputStream(PATH 用户信息表2007BigDataS.xlsx);workbook.write(fileOutputStream);fileOutputStream.close();long end System.currentTimeMillis();System.out.println((double) (end - begin) / 1000);//6.39s}
}
2.3、导入excel导入操作即将 excel 中的数据采用java工具库将其解析出来进而将 excel 数据写入数据库同样在 poi 工具库中导入 api 也分三种方式与上面的导出一一对应2.3.1、HSSF方式导入public class ExcelRead2003Test {public static String PATH /Users/hello/Desktop/;public static void main(String[] args) throws Exception {//获取文件流FileInputStream inputStream new FileInputStream(PATH 用户信息表BigData.xls);//1.创建工作簿,使用excel能操作的这边都看看操作Workbook workbook new HSSFWorkbook(inputStream);//2.得到表Sheet sheet workbook.getSheetAt(0);//3.得到行Row row sheet.getRow(0);//4.得到列Cell cell row.getCell(0);getValue(cell);inputStream.close();}public static void getValue(Cell cell){//匹配类型数据if (cell ! null) {CellType cellType cell.getCellType();String cellValue ;switch (cellType) {case STRING: //字符串System.out.print([String类型]);cellValue cell.getStringCellValue();break;case BOOLEAN: //布尔类型System.out.print([boolean类型]);cellValue String.valueOf(cell.getBooleanCellValue());break;case BLANK: //空System.out.print([BLANK类型]);break;case NUMERIC: //数字日期、普通数字System.out.print([NUMERIC类型]);if (HSSFDateUtil.isCellDateFormatted(cell)) { //日期System.out.print([日期]);Date date cell.getDateCellValue();cellValue new DateTime(date).toString(yyyy-MM-dd);} else {//不是日期格式防止数字过长System.out.print([转换为字符串输出]);cell.setCellType(CellType.STRING);cellValue cell.toString();}break;case ERROR:System.out.print([数据类型错误]);break;}System.out.println(cellValue);}}
}2.3.2、XSSF方式导入public class ExcelRead2007Test {public static String PATH /Users/hello/Desktop/;public static void main(String[] args) throws Exception {//获取文件流FileInputStream inputStream new FileInputStream(PATH 用户信息表2007BigData.xlsx);//1.创建工作簿,使用excel能操作的这边都看看操作Workbook workbook new XSSFWorkbook(inputStream);//2.得到表Sheet sheet workbook.getSheetAt(0);//3.得到行Row row sheet.getRow(0);//4.得到列Cell cell row.getCell(0);getValue(cell);inputStream.close();}public static void getValue(Cell cell){//匹配类型数据if (cell ! null) {CellType cellType cell.getCellType();String cellValue ;switch (cellType) {case STRING: //字符串System.out.print([String类型]);cellValue cell.getStringCellValue();break;case BOOLEAN: //布尔类型System.out.print([boolean类型]);cellValue String.valueOf(cell.getBooleanCellValue());break;case BLANK: //空System.out.print([BLANK类型]);break;case NUMERIC: //数字日期、普通数字System.out.print([NUMERIC类型]);if (HSSFDateUtil.isCellDateFormatted(cell)) { //日期System.out.print([日期]);Date date cell.getDateCellValue();cellValue new DateTime(date).toString(yyyy-MM-dd);} else {//不是日期格式防止数字过长System.out.print([转换为字符串输出]);cell.setCellType(CellType.STRING);cellValue cell.toString();}break;case ERROR:System.out.print([数据类型错误]);break;}System.out.println(cellValue);}}
}
2.3.3、SXSSF方式导入public class ExcelReadSXSSFTest {public static String PATH /Users/hello/Desktop/;public static void main(String[] args) throws Exception {//获取文件流//1.创建工作簿,使用excel能操作的这边都看看操作OPCPackage opcPackage OPCPackage.open(PATH 用户信息表2007BigData.xlsx);XSSFReader xssfReader new XSSFReader(opcPackage);StylesTable stylesTable xssfReader.getStylesTable();ReadOnlySharedStringsTable sharedStringsTable new ReadOnlySharedStringsTable(opcPackage);// 创建XMLReader设置ContentHandlerXMLReader xmlReader SAXHelper.newXMLReader();xmlReader.setContentHandler(new XSSFSheetXMLHandler(stylesTable, sharedStringsTable, new SimpleSheetContentsHandler(), false));// 解析每个Sheet数据IteratorInputStream sheetsData xssfReader.getSheetsData();while (sheetsData.hasNext()) {try (InputStream inputStream sheetsData.next();) {xmlReader.parse(new InputSource(inputStream));}}}/*** 内容处理器*/public static class SimpleSheetContentsHandler implements XSSFSheetXMLHandler.SheetContentsHandler {protected ListString row;/*** A row with the (zero based) row number has started** param rowNum*/Overridepublic void startRow(int rowNum) {row new ArrayList();}/*** A row with the (zero based) row number has ended** param rowNum*/Overridepublic void endRow(int rowNum) {if (row.isEmpty()) {return;}// 处理数据System.out.println(row.stream().collect(Collectors.joining( )));}/*** A cell, with the given formatted value (may be null),* and possibly a comment (may be null), was encountered** param cellReference* param formattedValue* param comment*/Overridepublic void cell(String cellReference, String formattedValue, XSSFComment comment) {row.add(formattedValue);}/*** A header or footer has been encountered** param text* param isHeader* param tagName*/Overridepublic void headerFooter(String text, boolean isHeader, String tagName) {}}}
三、easypoi以前的以前有个大佬程序员跳到一家公司之后就和业务人员聊上了这些业务员对excel报表有着许许多多的要求比如想要一个报表他的表头是一个多行表头过几天之后他想要给这些表头添加样式比如关键的数据标红再过几天他想要再末尾添加一条合计的数据等等起初还好都是copy、copy之后发现系统中出现大量的重复代码于是有一天真的忍受不了了采用注解搞定来搞定这些定制化成程度高的逻辑将公共化抽离出来于是诞生了 easypoieasypoi 的底层也是基于 apache poi 进行深度开发的它主要的特点就是将更多重复的工作全部简单化避免编写重复的代码下面我们就一起来了解一下这款高大上的开源工具easypoi3.1、首先添加依赖包dependenciesdependencygroupIdcn.afterturn/groupIdartifactIdeasypoi-base/artifactIdversion4.1.0/version/dependencydependencygroupIdcn.afterturn/groupIdartifactIdeasypoi-web/artifactIdversion4.1.0/version/dependencydependencygroupIdcn.afterturn/groupIdartifactIdeasypoi-annotation/artifactIdversion4.1.0/version/dependency
/dependencies
3.2、采用注解导出导入easypoi 最大的亮点就是基于注解实体类来导出、导入excel使用起来非常简单首先我们创建一个实体类UserEntity其中Excel注解表示导出文件的头部信息。public class UserEntity {Excel(name 姓名)private String name;Excel(name 年龄)private int age;Excel(name 操作时间,formatyyyy-MM-dd HH:mm:ss, width 20.0)private Date time;//set、get省略
}
接着我们来编写导出服务public static void main(String[] args) throws Exception {ListUserEntity dataList new ArrayList();for (int i 0; i 10; i) {UserEntity userEntity new UserEntity();userEntity.setName(张三 i);userEntity.setAge(20 i);userEntity.setTime(new Date(System.currentTimeMillis() i));dataList.add(userEntity);}//生成excel文档Workbook workbook ExcelExportUtil.exportExcel(new ExportParams(用户,用户信息),UserEntity.class, dataList);FileOutputStream fos new FileOutputStream(/Users/hello/Documents/easypoi-user1.xls);workbook.write(fos);fos.close();
}
导出的文件预览如下对应的导入操作也很简单源码如下public static void main(String[] args) {ImportParams params new ImportParams();params.setTitleRows(1);params.setHeadRows(1);long start new Date().getTime();ListStudentEntity list ExcelImportUtil.importExcel(new File(/Users/hello/Documents/easypoi-user1.xls),UserEntity.class, params);System.out.println(new Date().getTime() - start);System.out.println(JSONArray.toJSONString(list));
}
运行程序输出结果如下[{age:20,name:张三0,time:1616919493000},{age:21,name:张三1,time:1616919493000},{age:22,name:张三2,time:1616919493000},{age:23,name:张三3,time:1616919493000},{age:24,name:张三4,time:1616919493000},{age:25,name:张三5,time:1616919493000},{age:26,name:张三6,time:1616919493000},{age:27,name:张三7,time:1616919493000},{age:28,name:张三8,time:1616919493000},{age:29,name:张三9,time:1616919493000}]
3.3、自定义数据结构导出导入easypoi 同样也支持自定义数据结构导出导入excel。自定义数据导出 excelpublic static void main(String[] args) throws Exception {//封装表头ListExcelExportEntity entityList new ArrayListExcelExportEntity();entityList.add(new ExcelExportEntity(姓名, name));entityList.add(new ExcelExportEntity(年龄, age));ExcelExportEntity entityTime new ExcelExportEntity(操作时间, time);entityTime.setFormat(yyyy-MM-dd HH:mm:ss);entityTime.setWidth(20.0);entityList.add(entityTime);//封装数据体ListMapString, Object dataList new ArrayList();for (int i 0; i 10; i) {MapString, Object userEntityMap new HashMap();userEntityMap.put(name, 张三 i);userEntityMap.put(age, 20 i);userEntityMap.put(time, new Date(System.currentTimeMillis() i));dataList.add(userEntityMap);}//生成excel文档Workbook workbook ExcelExportUtil.exportExcel(new ExportParams(学生,用户信息), entityList, dataList);FileOutputStream fos new FileOutputStream(/Users/panzhi/Documents/easypoi-user2.xls);workbook.write(fos);fos.close();
}
导入 excelpublic static void main(String[] args) {ImportParams params new ImportParams();params.setTitleRows(1);params.setHeadRows(1);long start new Date().getTime();ListMapString, Object list ExcelImportUtil.importExcel(new File(/Users/panzhi/Documents/easypoi-user2.xls),Map.class, params);System.out.println(new Date().getTime() - start);System.out.println(JSONArray.toJSONString(list));
}
更多的 api 操作可以访问 Easypoi - 接口文档四、easyexceleasyexcel 是阿里巴巴开源的一款 excel 解析工具底层逻辑也是基于 apache poi 进行二次开发的。不同的是再读写数据的时候采用 sax 模式一行一行解析在并发量很大的情况下依然能稳定运行下面我们就一起来了解一下这款新起之秀4.1、首先添加依赖包dependenciesdependencygroupIdcom.alibaba/groupIdartifactIdeasyexcel/artifactIdversion2.2.6/version/dependency!--常用工具库--dependencygroupIdcom.google.guava/groupIdartifactIdguava/artifactIdversion29.0-jre/version/dependency
/dependencies
4.2、采用注解导出导入easyexcel 同样也支持采用注解方式进行导出、导入首先我们创建一个实体类UserEntity其中ExcelProperty注解表示导出文件的头部信息。public class UserEntity {ExcelProperty(value 姓名)private String name;ExcelProperty(value 年龄)private int age;DateTimeFormat(yyyy-MM-dd HH:mm:ss)ExcelProperty(value 操作时间)private Date time;//set、get省略
}
接着我们来编写导出服务public static void main(String[] args) {ListUserEntity dataList new ArrayList();for (int i 0; i 10; i) {UserEntity userEntity new UserEntity();userEntity.setName(张三 i);userEntity.setAge(20 i);userEntity.setTime(new Date(System.currentTimeMillis() i));dataList.add(userEntity);}EasyExcel.write(/Users/hello/Documents/easyexcel-user1.xls, UserEntity.class).sheet(用户信息).doWrite(dataList);
}
导出的文件预览如下对应的导入操作也很简单源码如下public static void main(String[] args) {String filePath /Users/hello/Documents/easyexcel-user1.xls;ListDemoData list EasyExcel.read(filePath).head(UserEntity.class).sheet().doReadSync();System.out.println(JSONArray.toJSONString(list));
}
运行程序输出结果如下[{age:20,name:张三0,time:1616920360000},{age:21,name:张三1,time:1616920360000},{age:22,name:张三2,time:1616920360000},{age:23,name:张三3,time:1616920360000},{age:24,name:张三4,time:1616920360000},{age:25,name:张三5,time:1616920360000},{age:26,name:张三6,time:1616920360000},{age:27,name:张三7,time:1616920360000},{age:28,name:张三8,time:1616920360000},{age:29,name:张三9,time:1616920360000}]
4.3、自定义数据结构导出导入easyexcel 同样也支持自定义数据结构导出导入excel。自定义数据导出 excelpublic static void main(String[] args) {//表头ListListString headList new ArrayList();headList.add(Lists.newArrayList(姓名));headList.add(Lists.newArrayList(年龄));headList.add(Lists.newArrayList(操作时间));//数据体ListListObject dataList new ArrayList();for (int i 0; i 10; i) {ListObject data new ArrayList();data.add(张三 i);data.add(20 i);data.add(new Date(System.currentTimeMillis() i));dataList.add(data);}EasyExcel.write(/Users/hello/Documents/easyexcel-user2.xls).head(headList).sheet(用户信息).doWrite(dataList);
}
导入 excelpublic static void main(String[] args) {String filePath /Users/panzhi/Documents/easyexcel-user2.xls;UserDataListener userDataListener new UserDataListener();EasyExcel.read(filePath, userDataListener).sheet().doRead();System.out.println(表头 JSONArray.toJSONString(userDataListener.getHeadList()));System.out.println(数据体 JSONArray.toJSONString(userDataListener.getDataList()));
}
运行程序输出结果如下表头[{0:姓名,1:年龄,2:操作时间}]
数据体[{0:张三0,1:20,2:2021-03-28 16:31:39},{0:张三1,1:21,2:2021-03-28 16:31:39},{0:张三2,1:22,2:2021-03-28 16:31:39},{0:张三3,1:23,2:2021-03-28 16:31:39},{0:张三4,1:24,2:2021-03-28 16:31:39},{0:张三5,1:25,2:2021-03-28 16:31:39},{0:张三6,1:26,2:2021-03-28 16:31:39},{0:张三7,1:27,2:2021-03-28 16:31:39},{0:张三8,1:28,2:2021-03-28 16:31:39},{0:张三9,1:29,2:2021-03-28 16:31:39}]
更多的 api 操作可以访问 easyexcel - 接口文档五、小结总体来说easypoi和easyexcel都是基于apache poi进行二次开发的。不同点在于1、easypoi 在读写数据的时候优先是先将数据写入内存优点是读写性能非常高但是当数据量很大的时候会出现oom当然它也提供了 sax 模式的读写方式需要调用特定的方法实现。2、easyexcel 基于sax模式进行读写数据不会出现oom情况程序有过高并发场景的验证因此程序运行比较稳定相对于 easypoi 来说读写性能稍慢easypoi 与 easyexcel 还有一点区别在于easypoi 对定制化的导出支持非常的丰富如果当前的项目需求并发量不大、数据量也不大但是需要导出 excel 的文件样式千差万别那么我推荐你用 easypoi反之使用 easyexcel 六、参考1、apache poi - 接口文档2、easypoi - 接口文档3、easyexcel - 接口文档