阿里EasyExcel

对文件execl的导入操作

        <!-- 阿里对execl操作 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>3.0.4</version>
        </dependency>

org.apache.poi.ss.usermodel.Cell.setBlank()V poi的jar版本太低问题

controller

/**
     人员绩效 excel文件的上传
     */
    @ApiOperation(value = "人员绩效 (导入execl)")
    @PostMapping("/uploadPersonExecl")
    public ControllerResult<?> uploadPersonExecl(MultipartFile file) {
        try {
            PersonRecordDataListener pzobj =  new PersonRecordDataListener(utilDao.getczyXmAndId(),personRecordDao);
            EasyExcel.read(file.getInputStream(), PersonPerformanceRecordDTO.class, pzobj).sheet().doRead();
            return new ControllerResult<>(true,pzobj.getSblist());
        } catch (IOException | ExcelAnalysisException e) {
            log.error("错误消息:{}",e.getMessage(),e);
            return new ControllerResult<>(false, "文件上传错误或格式不正确");
        } catch (Exception e) {
            log.error("错误消息:{}",e.getMessage(),e);
            return new ControllerResult<>(false, ErrorCode.SYSTEM_EXCEPTION);
        }
    }

第二种 没有办法获取对execl操作的结果

/**
 人员绩效 excel文件的上传
 */
@ApiOperation(value = "人员绩效 (导入execl)")
@PostMapping("/uploadPersonExecl")
public ControllerResult<?> uploadPersonExecl(MultipartFile file) {

    try {
        EasyExcel.read(file.getInputStream(), PersonPerformanceRecordDTO.class, personRecordDataListener).sheet().doRead();
        return new ControllerResult<>(true, "数据导入成功");
    } catch (IOException | ExcelAnalysisException e) {
        log.error("错误消息:{}",e.getMessage(),e);
        return new ControllerResult<>(false, "文件上传错误或格式不正确");
    } catch (Exception e) {
        log.error("错误消息:{}",e.getMessage(),e);
        return new ControllerResult<>(false, ErrorCode.SYSTEM_EXCEPTION);
    }
}

dto


import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.util.Date;

/**
 * @Author LiGuangLong
 * @Date 2021-11-09 10:45
 * @Version 1.0
 * table(person_performance_record)
 **/
@Data
@ApiModel("人员绩效")
public class PersonPerformanceRecordDTO {
    @ApiModelProperty("流水号")
    private String id;
    @ApiModelProperty("操作员代码")
    private Integer czydm;
    @ExcelProperty(index = 3)
    @ApiModelProperty("操作员姓名")
    private String czyxm;
    @ExcelProperty(index = 0)
    @ApiModelProperty("年份")
    private String year;
    @ExcelProperty(index = 1)
    @ApiModelProperty("季度(1-4)")
    private Integer quarter;
    @ExcelProperty(index = 2)
    @ApiModelProperty("站点")
    private String department;
    @ExcelProperty(index = 4)
    @ApiModelProperty("绩效(A-D)")
    private String performance;
    @ApiModelProperty("更新人员代码")
    private Integer updateCzydm;
    @ApiModelProperty("更新时间")
    private Date updateTime;
}

操作类

package com.eagle.monitor.reportForms.surplus.config;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.eagle.monitor.reportForms.surplus.dao.PersonRecordDao;
import com.eagle.monitor.reportForms.surplus.vo.PersonPerformanceRecordDTO;
import lombok.extern.slf4j.Slf4j;

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

/**
 * @Author LiGuangLong
 * @Date 2021-11-11 9:42
 * @Version 1.0
 **/
@Slf4j
public class PersonRecordDataListener extends AnalysisEventListener<PersonPerformanceRecordDTO> {
    private final Map<String,Object> mapList;
    private final PersonRecordDao personRecordDao;

    private List<String> sblist = new ArrayList();
    List<PersonPerformanceRecordDTO> list = new ArrayList<>();
    public PersonRecordDataListener(Map<String,Object> mapList,PersonRecordDao personRecordDao) {
        this.mapList = mapList;
        this.personRecordDao = personRecordDao;
    }

    /**
     * 这个每一条数据解析都会来调用
     *
     */
    @Override
    public void invoke(PersonPerformanceRecordDTO data, AnalysisContext context) {
        log.debug("解析到一条数据:");
        log.debug(data.toString());
        if (mapList.get(data.getCzyxm()) != null){
            Map<String,Integer> lsitmap = (Map<String, Integer>) mapList.get(data.getCzyxm());
            data.setCzydm(Integer.parseInt(String.valueOf(lsitmap.get("czydm"))));
        } else {
            sblist.add(data.getCzyxm());
        }
        list.add(data);
    }

    /**
     * 所有数据解析完成了 都会来调用
     *
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        log.debug(list.toString());
        personRecordDao.addPerson(list);
        list.clear();
    }
    public List<String> getSblist(){
        return this.sblist;
    }

}

这种方式没有办法获取导入结果


import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.eagle.monitor.reportForms.surplus.dao.PersonRecordDao;
import com.eagle.monitor.reportForms.surplus.dao.UtilDao;
import com.eagle.monitor.reportForms.surplus.vo.PersonPerformanceRecordDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @Author LiGuangLong
 * @Date 2021-11-11 9:42
 * @Version 1.0
 **/
@Component
@Slf4j
public class PersonRecordDataListener extends AnalysisEventListener<PersonPerformanceRecordDTO> {
    @Resource
    private UtilDao utilDao;
    private Map<String,Object> mapList;
    @Resource
    private PersonRecordDao personRecordDao;


    List<PersonPerformanceRecordDTO> list = new ArrayList<>();
    /**
     * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
     */
    public PersonRecordDataListener() {}
    @PostConstruct
    public void init() {
        this.mapList = utilDao.getczyXmAndId();
    }

    /**
     * 这个每一条数据解析都会来调用
     *
     * @param data
     * @param context
     */
    @Override
    public void invoke(PersonPerformanceRecordDTO data, AnalysisContext context) {
        log.debug("解析到一条数据:");
        log.debug(data.toString());
        if (mapList.get(data.getCzyxm()) != null){
            Map<String,Integer> lsitmap = (Map<String, Integer>) mapList.get(data.getCzyxm());
            data.setCzydm(Integer.parseInt(String.valueOf(lsitmap.get("czydm"))));
        }
        list.add(data);
    }

    /**
     * 所有数据解析完成了 都会来调用
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        log.debug(list.toString());
        personRecordDao.addPerson(list);
        list.clear();

    }

}

要点

定义好了表格数据类,就可以开始读取了,该库非常贴心,提供了 同步异步 两种读取方式。

同步读取

  // 读取到的数据
  List<YupiData> list = EasyExcel.read(fileName)
  	.head(YupiData.class)
    .sheet()
    .doReadSync();

异步方式需要定义一个 监听器 ,每读取一行,就要立即去处理该行数据。这样就不需要将所有数据都加载到内存中,算一行读一行,理论上算完了也可以丢弃。

不创建对象的读

如果事先不清楚表格会有哪些列、类型如何(比如让用户自主上传表格),那么可以使用 不创建对象读 的方式,直接用 Map<Integer, String> 泛型类来接收:

List<Map<Integer, String>> list = EasyExcel
    .read(fileName)
    .sheet()
    .doReadSync();
// Map 的 key 为列下标,value 为单元格的值
for (Map<Integer, String> data : list) {
	... 
}

写入表格

学会读取后,写入表格就更简单了,依然是先定义一个类,用来表示要写入表格的元信息(列名、列数据类型等)。

比如要完成表格列顺序调换的需求,定义表格数据类的时候,把 age 和 name 属性的顺序换一下就好了:

@Data
public class YupiWriteData {
  // 年龄 ↑
  private Integer age;
  // 姓名 ↓
  // 该注解设置 列明 列数位置
  @ExcelProperty(value = "正确检测数",index = 0)
  private String name;
  // 出生日期
  // 该注解让属性不被导出 默认全部导出
  @ExcelIgnore
  private Date bornDate;
}

然后执行 Easy Excel 的 write 方法,就完事了,代码如下:

void doWrite() {
  // 已读取和处理后的数据列表
  List<YupiWriteData> dataList = xxx;
  String fileName = "result.xlsx";
  EasyExcel.write(fileName, YupiWriteData.class)
      .sheet("工作表1")
      .doWrite(dataList);
}

搞定

导出格式设置

在字段添加注解

    @ContentStyle(dataFormat = 4)
    private Double doubleData;
 private static final String[] BUILTIN_FORMATS_CN = {
        // 0
        "General",
        // 1
        "0",
        // 2
        "0.00",
        // 3
        "#,##0",
        // 4
        "#,##0.00",
        // 5
        "\"¥\"#,##0_);(\"¥\"#,##0)",
        // 6
        "\"¥\"#,##0_);[Red](\"¥\"#,##0)",
        // 7
        "\"¥\"#,##0.00_);(\"¥\"#,##0.00)",
        // 8
        "\"¥\"#,##0.00_);[Red](\"¥\"#,##0.00)",
        // 9
        "0%",
        // 10
        "0.00%",
        // 11
        "0.00E+00",
        // 12
        "# ?/?",
        // 13
        "# ??/??",
        // 14
        // The official documentation shows "m/d/yy", but the actual test is "yyyy/m/d".
        "yyyy/m/d",
        // 15
        "d-mmm-yy",
        // 16
        "d-mmm",
        // 17
        "mmm-yy",
        // 18
        "h:mm AM/PM",
        // 19
        "h:mm:ss AM/PM",
        // 20
        "h:mm",
        // 21
        "h:mm:ss",
        // 22
        // The official documentation shows "m/d/yy h:mm", but the actual test is "yyyy-m-d h:mm".
        "yyyy-m-d h:mm",
        // 23-26 No specific correspondence found in the official documentation.
        // 23
        null,
        // 24
        null,
        // 25
        null,
        // 26
        null,
        // 27
        "yyyy\"年\"m\"月\"",
        // 28
        "m\"月\"d\"日\"",
        // 29
        "m\"月\"d\"日\"",
        // 30
        "m-d-yy",
        // 31
        "yyyy\"年\"m\"月\"d\"日\"",
        // 32
        "h\"时\"mm\"分\"",
        // 33
        "h\"时\"mm\"分\"ss\"秒\"",
        // 34
        "上午/下午h\"时\"mm\"分\"",
        // 35
        "上午/下午h\"时\"mm\"分\"ss\"秒\"",
        // 36
        "yyyy\"年\"m\"月\"",
        // 37
        "#,##0_);(#,##0)",
        // 38
        "#,##0_);[Red](#,##0)",
        // 39
        "#,##0.00_);(#,##0.00)",
        // 40
        "#,##0.00_);[Red](#,##0.00)",
        // 41
        "_(* #,##0_);_(* (#,##0);_(* \"-\"_);_(@_)",
        // 42
        "_(\"¥\"* #,##0_);_(\"¥\"* (#,##0);_(\"¥\"* \"-\"_);_(@_)",
        // 43
        "_(* #,##0.00_);_(* (#,##0.00);_(* \"-\"??_);_(@_)",
        // 44
        "_(\"¥\"* #,##0.00_);_(\"¥\"* (#,##0.00);_(\"¥\"* \"-\"??_);_(@_)",
        // 45
        "mm:ss",
        // 46
        "[h]:mm:ss",
        // 47
        "mm:ss.0",
        // 48
        "##0.0E+0",
        // 49
        "@",
        // 50
        "yyyy\"年\"m\"月\"",
        // 51
        "m\"月\"d\"日\"",
        // 52
        "yyyy\"年\"m\"月\"",
        // 53
        "m\"月\"d\"日\"",
        // 54
        "m\"月\"d\"日\"",
        // 55
        "上午/下午h\"时\"mm\"分\"",
        // 56
        "上午/下午h\"时\"mm\"分\"ss\"秒\"",
        // 57
        "yyyy\"年\"m\"月\"",
        // 58
        "m\"月\"d\"日\"",
        // 59
        "t0",
        // 60
        "t0.00",
        // 61
        "t#,##0",
        // 62
        "t#,##0.00",
        // 63-66 No specific correspondence found in the official documentation.
        // 63
        null,
        // 64
        null,
        // 65
        null,
        // 66
        null,
        // 67
        "t0%",
        // 68
        "t0.00%",
        // 69
        "t# ?/?",
        // 70
        "t# ??/??",
        // 71
        "ว/ด/ปปปป",
        // 72
        "ว-ดดด-ปป",
        // 73
        "ว-ดดด",
        // 74
        "ดดด-ปป",
        // 75
        "ช:นน",
        // 76
        "ช:นน:ทท",
        // 77
        "ว/ด/ปปปป ช:นน",
        // 78
        "นน:ทท",
        // 79
        "[ช]:นน:ทท",
        // 80
        "นน:ทท.0",
        // 81
        "d/m/bb",
        // end
    };
posted @ 2021-11-12 17:46  李广龙  阅读(853)  评论(0)    收藏  举报