【工具使用】【EasyExcel 】EasyExcel 实现 Excel 作者信息、版本信息等的写入和读取
1 前言
导入的功能,想必大家都做过,大家肯定也都遇到过比如我的模板变化了(比如新增一列、删除一列等),客户在使用的时候可能还是用的老模板进行导入,那么我们在写代码的时候,应该怎么快速识别到呢?
比如可以比较客户导入的 Excel 一列一列的去比较或者列的个数等是可以的。
我想的一个是能不能给 Excel 写入一个版本信息,类型属性信息这种,这样在导入的时候,我可以比较一下这个版本号,来提示用户当前版本,最新版本让客户下载新的模板。
当时没空整,这不是空了,那我们本节就来小小的研究一下。
Excel 官网:官方文档我看了,没有关于这种属性信息、作者信息这种的写入、读取
Excel 依赖:
<!--工具 excel--> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>4.0.2</version> <exclusions> <exclusion> <artifactId>poi-ooxml-schemas</artifactId> <groupId>org.apache.poi</groupId> </exclusion> </exclusions> </dependency>
2 实现
我这里就直接贴代码了哈:
主类:
package com.virtuous.demo.laboratory.excel; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.util.ListUtils; import java.util.Date; import java.util.List; /** * @author: kuku * @description */ public class TemplateDownload { public static void main(String[] args) { // 文件名 String fileName = "test.xlsx"; // 写 excel EasyExcel.write(fileName) .registerWriteHandler(new CustomSheetWriteHandler()) .sheet("模板").doWrite(dataList()); // 读 excel EasyExcel.read("test.xlsx", new ReadDataListener()).sheet().doRead(); } private static List<List<Object>> dataList() { List<List<Object>> list = ListUtils.newArrayList(); for (int i = 0; i < 10; i++) { List<Object> data = ListUtils.newArrayList(); data.add("字符串" + i); data.add(0.56); data.add(new Date()); list.add(data); } return list; } }
写入的拦截器,用于对 Excel 进行一些特定的写入:
package com.virtuous.demo.laboratory.excel; import com.alibaba.excel.write.handler.SheetWriteHandler; import com.alibaba.excel.write.handler.context.SheetWriteHandlerContext; import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.poi.ooxml.POIXMLProperties; import org.apache.poi.xssf.streaming.SXSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import java.lang.reflect.Field; /** * 写 ExceL 拦截器 * @author kuku */ @Slf4j public class CustomSheetWriteHandler implements SheetWriteHandler { @SneakyThrows @Override public void afterSheetCreate(SheetWriteHandlerContext context) { // 获取到当前的 workbook WriteWorkbookHolder writeWorkbookHolder = context.getWriteWorkbookHolder(); // 由于没有直接的获取方式 我们这里用反射 Field workbookField = WriteWorkbookHolder.class.getDeclaredField("workbook"); workbookField.setAccessible(true); SXSSFWorkbook sxssfWorkbook = (SXSSFWorkbook)workbookField.get(writeWorkbookHolder); XSSFWorkbook xssfWorkbook = sxssfWorkbook.getXSSFWorkbook(); // 获取属性对象 POIXMLProperties properties = xssfWorkbook.getProperties(); POIXMLProperties.CoreProperties coreProperties = properties.getCoreProperties(); String creator = "酷酷2024"; String description = "订单导入模板"; String version = "2.0"; // 设置作者信息 coreProperties.setCreator(creator); // 设置描述信息 coreProperties.setDescription(description); // 设置版本号 coreProperties.setVersion(version); log.info("写入作者:{},描述:{},版本:{}", creator, description, version); } }
读取的监听器:
package com.virtuous.demo.laboratory.excel; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; import com.alibaba.excel.read.metadata.holder.ReadWorkbookHolder; import com.alibaba.excel.read.metadata.holder.xlsx.XlsxReadWorkbookHolder; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.PackageProperties; import java.lang.reflect.Field; import java.util.Map; /** * 读 Excel 监听器 * @author kuku */ @Slf4j public class ReadDataListener extends AnalysisEventListener<Map<Integer, String>> { @Override public void invoke(Map<Integer, String> data, AnalysisContext context) { } @SneakyThrows @Override public void doAfterAllAnalysed(AnalysisContext context) { ReadWorkbookHolder readWorkbookHolder = context.readWorkbookHolder(); if (readWorkbookHolder instanceof XlsxReadWorkbookHolder) { Field opcPackageField = XlsxReadWorkbookHolder.class.getDeclaredField("opcPackage"); opcPackageField.setAccessible(true); OPCPackage opcPackage = (OPCPackage) opcPackageField.get(readWorkbookHolder); PackageProperties packageProperties = opcPackage.getPackageProperties(); String creator = packageProperties.getCreatorProperty().orElse(null); String description = packageProperties.getDescriptionProperty().orElse(null); String version = packageProperties.getVersionProperty().orElse(null); log.info("读取作者:{},描述:{},版本:{}", creator, description, version); } } }
最后说一下:这种属性信息比如版本、作者信息等是可以自己编辑的,哈哈哈,当然这种概率比较小,我估计影响不大,如果要非常严谨的话,还是一列一列的去比较校验。
另外 POI 方式的就不写了哈,写入和读取基本都是用的 POI 里的对象,方式是一样的。
还有有的一些反射以及类型的校验,大家可以再严谨点,我这里主要是测试下看看行不行,所以直接 @SneakyThrows 来大包大揽了哈。
3 小结
好啦,本节就看到这里,有理解不对的地方欢迎指正哈。