阿里巴巴EasyExcel使用(3)-导入

导入的话比较简单了,参照官方文档,有好几个Demo。

我这里主要考虑几个情况: ①数据量较大,分批读取 ②数据格式需要校验,因为导入的数据有可能存在格式问题,但是需要给前端提醒一下哪里出错了.

一、Excel数据

这里在数字格式的地方用字符串导入,引起出错~

二、API 调用

这里参考官方文档,修改的地方在DemoExceptionListener监听类里面

  /**
     * 数据转换等异常处理
     *
     * <p>
     * 1. 创建excel对应的实体对象 参照{@link ExceptionDemoData}
     * <p>
     * 2. 由于默认异步读取excel,所以需要创建excel一行一行的回调监听器,参照{@link DemoExceptionListener}
     * <p>
     * 3. 直接读即可
     */
    @Test
    public void exceptionRead() {
        String fileName = "I:\\temp\\readDemo1.xlsx";
        // 这里 需要指定读用哪个class去读,然后读取第一个sheet
        EasyExcel.read(fileName, ExceptionDemoData.class, new DemoExceptionListener()).sheet().doRead();
    }
/**
 * 基础数据类.这里的排序和excel里面的排序一致
 *
 **/
@Data
public class ExceptionDemoData {
    
    private String string;
    private Date date;
    private Double doubleData;

}

三、DemoExceptionListener监听类

主要内部定义一个存储异常信息的StringBuffer,用于收集异常,并在读取完Excel之后可以用于校验是否转换数据出错~

/**
 * 读取转换异常
 *  
 */
public class DemoExceptionListener extends AnalysisEventListener<ExceptionDemoData> {
    private static final Logger LOGGER = LoggerFactory.getLogger(DemoExceptionListener.class);
    /**
     * 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 5;
    List<ExceptionDemoData> list = new ArrayList<ExceptionDemoData>();

    //定义接收异常
    private StringBuffer  errorMsg;


    /**
     * 在转换异常 获取其他异常下会调用本接口。抛出异常则停止读取。如果这里不抛出异常则 继续读取下一行。
     *
     * @param exception
     * @param context
     * @throws Exception
     */
    @Override
    public void onException(Exception exception, AnalysisContext context) {
        LOGGER.error("解析失败,但是继续解析下一行:{}", exception.getMessage());
        // 如果是某一个单元格的转换异常 能获取到具体行号
        // 如果要获取头的信息 配合invokeHeadMap使用
        if (exception instanceof ExcelDataConvertException) {
            ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException)exception;
            LOGGER.error("第{}行,第{}列解析异常,数据为:{}", excelDataConvertException.getRowIndex(),
                excelDataConvertException.getColumnIndex(), excelDataConvertException.getCellData());
            String msg="第"+excelDataConvertException.getRowIndex()+"行,第"+excelDataConvertException.getColumnIndex()+"列解析异常,数据为:"+
        excelDataConvertException.getCellData(); if(errorMsg==null){ errorMsg=new StringBuffer(); } //拼接报错信息
errorMsg.append(msg).append(System.lineSeparator()); } } /** * 这里会一行行的返回头 * * @param headMap * @param context */ @Override public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) { LOGGER.info("解析到一条头数据:{}", JSON.toJSONString(headMap)); } @Override public void invoke(ExceptionDemoData data, AnalysisContext context) { LOGGER.info("解析到一条数据:{}", JSON.toJSONString(data)); if (list.size() >= BATCH_COUNT) { //操作数据之前统一判断异常信息,可以直接抛异常 if (errorMsg != null && errorMsg.length() > 0) { // throw new RuntimeException("解析数据异常!!信息:"+errorMsg.toString()); LOGGER.error("解析数据异常!!信息:" + errorMsg.toString()); } saveData(); list.clear(); } } @Override public void doAfterAllAnalysed(AnalysisContext context) { ////操作数据之前统一判断异常信息 /*if (errorMsg != null && errorMsg.length() > 0) { // throw new RuntimeException("解析数据异常!!信息:"+errorMsg.toString()); LOGGER.error("解析数据异常!!信息:" + errorMsg.toString()); }else{ LOGGER.info("所有数据解析完成!"); //解析完成无错误保存数据 saveData(); }*/ } /** * 加上存储数据库 */ private void saveData() { LOGGER.info("{}条数据,开始存储数据库!", list.size()); LOGGER.info("存储数据库成功!"); } }

四、总结

这里不知道有没有线程安全和变量未回收问题。

猜你喜欢

转载自www.cnblogs.com/coloz/p/12559558.html
今日推荐