EasyExcel工具使用教程


一、数据读取

1. 模拟数据

首先先准备一个 Excel 数据文件,文件内容如下:

id    name    gender    birthday
1    User-1    Male    2024-01-29
2    User-2    Male    2024-01-29
3    User-3    Male    2024-01-29
4    User-4    Male    2024-01-29

2. 实体读取

EasyExcel 支持匹配 Java 实体读取文件内容,文件的列名需要何 Java 类的字段名相对应。

如下示例中即读取第一步中的模拟数据最终返回一个列表集合。

public class ExcelUser {

    private String id;

    private String name;

    private String gender;

    private Date birthday;
}

public class ExcelReadTest {

    @Test
    public void readDemo2() {
        String fileLocate = "src\\main\\resources\\info.xls";
        try (InputStream in = Files.newInputStream(Paths.get(fileLocate))) {
            List<ExcelUser> list = EasyExcel.read(in)
                    .head(ExcelUser.class)
                    .sheet()
                    .doReadSync();
            System.out.println(list);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

3. 动态读取

EasyExcel 除了支持实体类读取之外还可以动态指定列名进行读取,返回的结果为 List<LinkedMap<Integer, Object>>,其中每一个 LinkMap 对应文件内的一行数据。

需要注意这里传入的列头集合类型是 List<List<String>> 而非 List<String>,即数据格式如:[["id"], ["name"]]。同时 EasyExcel 支持多种读入方式,在上一点示例中通过 IO 方法读取,下述示例则直接传入文件路径,可根据需要选择。

public void readDemo1() {
    String fileLocate = "src\\main\\resources\\info.xls";
    List<List<String>> heads = Stream.of("id", "name", "gender", "birthday")
            .map(Arrays::asList)
            .collect(Collectors.toList());
    List<LinkedMap<Integer, Object>> list = EasyExcel.read(fileLocate)
            .head(heads)
            .sheet()
            .doReadSync();
    System.out.println(list);
}

二、数据写入

1. 写入示例

EasyExcel 写入操作与读取类似,其中的 excelType 为文件类型,可选值有下述三类,对应三种不同的数据文件格式。

ExcelTypeEnum.CSV
ExcelTypeEnum.XLS
ExcelTypeEnum.XLSX

这里同样是采取实体字段名匹配的方式写入数据,示例代码如下:

public void readDemo1() {
    List<ExcelUser> dataList = new ArrayList<>();
    for (int i = 1; i < 5; i++) {
        dataList.add(new ExcelUser(i + "", "User-" + i, "Male", new Date()));
    }

    String fileLocate = "src\\main\\resources\\info.xls";
    EasyExcel.write(fileLocate)
            .excelType(ExcelTypeEnum.XLS)
            .head(ExcelUser.class)
            .sheet("Test-data")
            .doWrite(data);
}

2. Sheet管理

当需要写入多个 Sheet 到同一个 Excel 文件时,即可使用 ExcelWriterSheetBuilder

如下述示例中即创建两个 Sheet 页数据,Sheet 页名称分别为 Sheet-1Sheet-2

 public void multipleWrite() throws IOException {
    List<ExcelUser> dataList = new ArrayList<>();
    for (int i = 1; i < 5; i++) {
        dataList.add(new ExcelUser(i + "", "User-" + i, "Male", new Date()));
    }

    String fileLocate = "src\\main\\resources\\info.xls";
    ExcelWriter excelWriter = EasyExcel.write(fileLocate)
            .excelType(ExcelTypeEnum.XLS)
            .build();
    // 循环创建两个 Sheet 页数据
    for (int i = 1; i <= 2; i++) {
        ExcelWriterSheetBuilder sheetBuilder = new ExcelWriterSheetBuilder(excelWriter);
        sheetBuilder.sheetName("Sheet-" + i);
        sheetBuilder.head(ExcelUser.class);
        sheetBuilder.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy());
        excelWriter.write(dataList, sheetBuilder.build());
    }
    excelWriter.finish();
}

3. 动态写入

在许多场景下数据是变动的通过实体匹配显然是不合适的,因此 EasyExcel 提供了动态写入的能力。

与上述提到的读取和写入类似,其列名通过 List<List<String>> 指定,但不同的是其数据的载体是 List<Object> 而非 List<Map>,因此在写入时我们需要将后者数据格式转为 List<Object>,对应的数据转化样例如下:

// List<Map<String, Object>>
[
    { 
        "id": "1", 
        "name": "user-1", 
        "gender": "Male", 
        "birthday": "2023-01-01 00:00:01"
    },
    { 
        "id": "2", 
        "name": "user-2", 
        "gender": "Male", 
        "birthday": "2023-01-01 00:00:02"
    }
]

// List<Object>
[
    ["1", "user-1", "Male", "2023-01-01 00:00:01"],
    ["2", "user-2", "Male", "2023-01-01 00:00:02"]
]

根据上述逻辑,其相对应的程序代码如下:

public void dynamicWrite() throws IOException {
    List<Map<String, Object>> dataList = new ArrayList<>();
    for (int i = 1; i < 5; i++) {
        Map<String, Object> map = Map.of(
                "id", i + "",
                "name", "user-" + i,
                "gender", "Male",
                "birthday", new Date()
        );
        dataList.add(map)
    }
    // Convert "List<Map<?, ?>>" to "List<?>"
    List<List<Object>> rowDatas = new ArrayList<>();
    for (Map<String, Object> map : dataList) {
        List<Object> row = new ArrayList<>();
        for (String name : headList) {
            row.add(map.get(name));
        }
        rowDatas.add(row);
    }
    // Excel head
    List<List<String>> heads = Stream.of("id", "name", "gender", "birthday")
            .map(Arrays::asList)
            .collect(Collectors.toList());
    // Writer data
    String fileLocate = "src\\main\\resources\\info.xls";
    EasyExcel.write(fileLocate)
            .excelType(ExcelTypeEnum.XLS)
            .head(heads)
            .sheet("Test-data")
            .doWrite(rowDatas);
}

三、注解使用

1. ExcelProperty

@ExcelProperty 注解存在 valueorder 两个属性,前者用于设置别名,后者用于设置列顺序。

如下示例中则最后生成 Excel 文件中列名分别为 编号姓名,其中第一列为 编号,第二列为 姓名

public class ExcelUser {

    @ExcelProperty(value = "编号", order = 1)
    private String id;

    @ExcelProperty(value = "姓名", order = 2)
    private String name;
}

2. ExcelIgnore

@ExcelIgnore 用于指定需要忽略的属性。

如下示例在读取或写入文件时将忽略 address 字段。

public class ExcelUser {

    private String id;

    @ExcelIgnore
    private Date address;
}

3. DateTimeFormat

@DateTimeFormat 用于指定格式化字段时间

如下示例在读取或写入文件时将会格式化字段 birthday 字段 值为 yyy-MM-dd 格式。

public class ExcelUser {

    private String id;

    @DateTimeFormat("yyy-MM-dd")
    private Date birthday;
}

文章作者: 烽火戏诸诸诸侯
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 烽火戏诸诸诸侯 !
  目录