【工具使用】【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  小结

好啦,本节就看到这里,有理解不对的地方欢迎指正哈。

posted @ 2024-09-05 13:39  酷酷-  阅读(375)  评论(0编辑  收藏  举报