EasyExcel读文件的使用模板

EasyExcel

EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。

官网:(https://github.com/alibaba/easyexcel)

常见api · 语雀 (https://www.yuque.com/easyexcel/doc/api)。

定义格式

package com.bootcrab.cos.dto.coms.easyexcel;

import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.annotations.ApiModelProperty;
/**
 * @author ZhzGod
 * @date 2022/4/25 17:44
 * @introduction
 */
public class CardIdentifierRequestDTO {
    /**
     * 客户编号
     */
	//@ExcelProperty("客户编号")
    @ExcelProperty(index = 0)
    private String customerId;

    public String getCustomerId() {
        return customerId;
    }

    public void setCustomerId(String customerId) {
        this.customerId = customerId;
    }

}

监听模板

package com.bootcrab.cos.service.coms.notice.batch.easyexcel;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.excel.metadata.CellExtra;
import com.alibaba.fastjson.JSON;
import com.bootcrab.cos.dto.coms.easyexcel.CardIdentifierRequestDTO;
import com.bootcrab.cos.service.third.social.CreditInfoInquireService;
import com.bootcrab.cos.util.DateProUtil;
import com.bootcrab.cos.xface.dto.maintenance.ocr.dopa.XfaceCardIdentifierRequestDTO;
import com.bootcrab.cos.xface.dto.maintenance.ocr.dopa.XfaceCardIdentifierResponseDTO;
import com.bootcrabframework.cloud.core.component.SessionContext;
import com.bootcrabframework.cloud.core.util.CommonUtil;
import com.bootcrabframework.cloud.core.util.IDUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * @author ZhzGod
 * @date 2022/4/25 18:05
 * @introduction
 */
public class DemoTestListener extends AnalysisEventListener<CardIdentifierRequestDTO> {


    private CreditInfoInquireService creditInfoInquireService;
    private static int cnt=1;

	//注入service
    public DemoTestListener(CreditInfoInquireService creditInfoInquireService) {
        this.creditInfoInquireService = creditInfoInquireService;
    }




    private static final Logger LOGGER = LoggerFactory.getLogger(DemoTestListener.class);
    /**
     * 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 5;
    List<CardIdentifierRequestDTO> list = new ArrayList<CardIdentifierRequestDTO>();

    /**
     * 读取时,每条数据都会从这里解析
     */
    @Override
    public void invoke(CardIdentifierRequestDTO data, AnalysisContext context) {
//        LOGGER.info("解析到一条数据:{}", JSON.toJSONString(data));
        list.add(data);
        cnt++;
        // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
        if (list.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            list.clear();
        }
    }

    /**
     * 所有数据解析完成了 都会来调用
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        saveData();
        LOGGER.info("所有数据解析完成!");
    }
    /**
     * 加上存储数据库
     */
    private void saveData() {
//        LOGGER.info("{}条数据,开始存储数据库!", list.size());
        //这里真实的保存数据。
//        LOGGER.info("存储数据库成功!");
    }

    /**
     * 读取表头数据
     */
    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        LOGGER.info("解析到一条头数据:{}", JSON.toJSONString(headMap));
    }

    /**
     * 读取额外信息
     * @param extra
     * @param context
     */
    @Override
    public void extra(CellExtra extra, AnalysisContext context) {
        LOGGER.info("读取到了一条额外信息:{}", JSON.toJSONString(extra));
        switch (extra.getType()) {
            case COMMENT:
                LOGGER.info("额外信息是批注,在rowIndex:{},columnIndex;{},内容是:{}", extra.getRowIndex(), extra.getColumnIndex(),
                        extra.getText());
                break;
            case HYPERLINK:
                if ("Sheet1!A1".equals(extra.getText())) {
                    LOGGER.info("额外信息是超链接,在rowIndex:{},columnIndex;{},内容是:{}", extra.getRowIndex(),
                            extra.getColumnIndex(), extra.getText());
                } else if ("Sheet2!A1".equals(extra.getText())) {
                    LOGGER.info(
                            "额外信息是超链接,而且覆盖了一个区间,在firstRowIndex:{},firstColumnIndex;{},lastRowIndex:{},lastColumnIndex:{},"
                                    + "内容是:{}",
                            extra.getFirstRowIndex(), extra.getFirstColumnIndex(), extra.getLastRowIndex(),
                            extra.getLastColumnIndex(), extra.getText());
                } else {
                    LOGGER.info("Unknown hyperlink!");
                }
                break;
            case MERGE:
                LOGGER.info(
                        "额外信息是超链接,而且覆盖了一个区间,在firstRowIndex:{},firstColumnIndex;{},lastRowIndex:{},lastColumnIndex:{}",
                        extra.getFirstRowIndex(), extra.getFirstColumnIndex(), extra.getLastRowIndex(),
                        extra.getLastColumnIndex());
                break;
            default:
        }
    }

    /**
     * 用日期去接字符串 肯定报错,此时需要用到异常处理
     * 在转换异常获取其他异常下会调用本接口。
     * 抛出异常则停止读取。如果这里不抛出异常则 继续读取下一行。
     */
    @Override
    public void onException(Exception exception, AnalysisContext context) {
        LOGGER.error("第{}行,解析失败,但是继续解析下一行:{}",cnt,exception.getMessage());
        // 如果是某一个单元格的转换异常 能获取到具体行号
        // 如果要获取头的信息 配合invokeHeadMap使用
        if (exception instanceof ExcelDataConvertException) {
            ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException)exception;
            LOGGER.error("第{}行,第{}列解析异常", excelDataConvertException.getRowIndex(),
                    excelDataConvertException.getColumnIndex());
        }
    }
}

main方法测试:

public class DemoMain {
    public static void main(String[] args) {
        String fileName = "D:\\excel.xlsx";
        //读取单个sheet
        EasyExcel.read(fileName, ImportContent.class, new DemoTestListener())
                // 需要读取批注 默认不读取
                .extraRead(CellExtraTypeEnum.COMMENT)
                // 需要读取超链接 默认不读取
                .extraRead(CellExtraTypeEnum.HYPERLINK)
                // 需要读取合并单元格信息 默认不读取
                .extraRead(CellExtraTypeEnum.MERGE).sheet()
                .doRead();
        //多个sheet,读取全部
        // 这里需要注意 DemoDataListener的doAfterAllAnalysed 会在每个sheet读取完毕后调用一次。然后所有sheet都会往同一个DemoDataListener里面写。
        EasyExcel.read(fileName, ImportContent.class, new DemoTestListener()).doReadAll();
 
        //以下定义自定义格式转换
        EasyExcel.read(fileName, ImportContent.class, new DemoTestListener())
                // 若全局使用自定义转换可以用registerConverter,所有java为string,excel为string的都会用这个转换器。
                // 如果就想单个字段使用请使用@ExcelProperty 指定converter
                // .registerConverter(new CustomStringStringConverter())
                .sheet()
                //如果多行头,可以设置其他值。默认第一行为行头。
                .headRowNumber(1)
                .doRead();
 
        //可以同步返回进行数据处理,但是不推荐,数据量大会放到内存里。
        List<ImportContent> list = EasyExcel.read(fileName).head(ImportContent.class).sheet().doReadSync();
 
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值