alibaba easyexcel 官方教程,附详细说明、例子、源码

原文链接地址:https://alibaba-easyexcel.github.io/index.html

是个非常好的参考文档,比网上其他网有写的都靠谱、动态更新、详细

以下是一个写列子,建议点击目录,跳转到官方链接,体验更好

alibaba easyexcel 官方教程,附详细说明、例子、源码

Easy Excel

 

通用数据生成 后面不会重复写

1
2
3
4
5
6
7
8
9
10
11
private List<DemoData> data() {
    List<DemoData> list = new ArrayList<DemoData>();
    for (int i = 0; i < 10; i++) {
        DemoData data = new DemoData();
        data.setString("字符串" + i);
        data.setDate(new Date());
        data.setDoubleData(0.56);
        list.add(data);
    }
    return list;
}

示例代码

DEMO代码地址:https://github.com/alibaba/easyexcel/blob/master/src/test/java/com/alibaba/easyexcel/test/demo/write/WriteTest.java

最简单的写

excel示例

alibaba easyexcel 官方教程,附详细说明、例子、源码

对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Data
public class DemoData {
    @ExcelProperty("字符串标题")
    private String string;
    @ExcelProperty("日期标题")
    private Date date;
    @ExcelProperty("数字标题")
    private Double doubleData;
    /**
     * 忽略这个字段
     */
    @ExcelIgnore
    private String ignore;
}

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
 * 最简单的写
 * <p>1. 创建excel对应的实体对象 参照{@link DemoData}
 * <p>2. 直接写即可
 */
@Test
public void simpleWrite() {
    // 写法1
    String fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";
    // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
    // 如果这里想使用03 则 传入excelType参数即可
    EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());

    // 写法2
    fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";
    // 这里 需要指定写用哪个class去写
    ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build();
    WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
    excelWriter.write(data(), writeSheet);
    // 千万别忘记finish 会帮忙关闭流
    excelWriter.finish();
}

根据参数只导出指定列

excel示例

alibaba easyexcel 官方教程,附详细说明、例子、源码

对象

参照:对象

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
 * 根据参数只导出指定列
 * <p>
 * 1. 创建excel对应的实体对象 参照{@link DemoData}
 * <p>
 * 2. 根据自己或者排除自己需要的列
 * <p>
 * 3. 直接写即可
 *
 * @since 2.1.1
 */
@Test
public void excludeOrIncludeWrite() {
    String fileName = TestFileUtil.getPath() + "excludeOrIncludeWrite" + System.currentTimeMillis() + ".xlsx";

    // 根据用户传入字段 假设我们要忽略 date
    Set<String> excludeColumnFiledNames = new HashSet<String>();
    excludeColumnFiledNames.add("date");
    // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
    EasyExcel.write(fileName, DemoData.class).excludeColumnFiledNames(excludeColumnFiledNames).sheet("模板")
        .doWrite(data());

    fileName = TestFileUtil.getPath() + "excludeOrIncludeWrite" + System.currentTimeMillis() + ".xlsx";
    // 根据用户传入字段 假设我们只要导出 date
    Set<String> includeColumnFiledNames = new HashSet<String>();
    includeColumnFiledNames.add("date");
    // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
    EasyExcel.write(fileName, DemoData.class).includeColumnFiledNames(includeColumnFiledNames).sheet("模板")
        .doWrite(data());
}

指定写入的列

excel示例

alibaba easyexcel 官方教程,附详细说明、例子、源码

对象

1
2
3
4
5
6
7
8
9
10
11
12
@Data
public class IndexData {
    @ExcelProperty(value = "字符串标题", index = 0)
    private String string;
    @ExcelProperty(value = "日期标题", index = 1)
    private Date date;
    /**
     * 这里设置3 会导致第二列空的
     */
    @ExcelProperty(value = "数字标题", index = 3)
    private Double doubleData;
}

代码

1
2
3
4
5
6
7
8
9
10
11
12
/**
 * 指定写入的列
 * <p>1. 创建excel对应的实体对象 参照{@link IndexData}
 * <p>2. 使用{@link ExcelProperty}注解指定写入的列
 * <p>3. 直接写即可
 */
@Test
public void indexWrite() {
    String fileName = TestFileUtil.getPath() + "indexWrite" + System.currentTimeMillis() + ".xlsx";
    // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
    EasyExcel.write(fileName, IndexData.class).sheet("模板").doWrite(data());
}

复杂头写入

excel示例

 

alibaba easyexcel 官方教程,附详细说明、例子、源码

对象

1
2
3
4
5
6
7
8
9
@Data
public class ComplexHeadData {
    @ExcelProperty({"主标题", "字符串标题"})
    private String string;
    @ExcelProperty({"主标题", "日期标题"})
    private Date date;
    @ExcelProperty({"主标题", "数字标题"})
    private Double doubleData;
}

代码

1
2
3
4
5
6
7
8
9
10
11
12
/**
 * 复杂头写入
 * <p>1. 创建excel对应的实体对象 参照{@link ComplexHeadData}
 * <p>2. 使用{@link ExcelProperty}注解指定复杂的头
 * <p>3. 直接写即可
 */
@Test
public void complexHeadWrite() {
    String fileName = TestFileUtil.getPath() + "complexHeadWrite" + System.currentTimeMillis() + ".xlsx";
    // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
    EasyExcel.write(fileName, ComplexHeadData.class).sheet("模板").doWrite(data());
}

重复多次写入(写到单个或者多个Sheet)

excel示例

alibaba easyexcel 官方教程,附详细说明、例子、源码

对象

参照:对象

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/**
   * 重复多次写入(写到单个或者多个Sheet)
   * <p>
   * 1. 创建excel对应的实体对象 参照{@link ComplexHeadData}
   * <p>
   * 2. 使用{@link ExcelProperty}注解指定复杂的头
   * <p>
   * 3. 直接调用二次写入即可
   */
  @Test
  public void repeatedWrite() {
      // 方法1 如果写到同一个sheet
      String fileName = TestFileUtil.getPath() + "repeatedWrite" + System.currentTimeMillis() + ".xlsx";
      // 这里 需要指定写用哪个class去写
      ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build();
      // 这里注意 如果同一个sheet只要创建一次
      WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
      // 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来
      for (int i = 0; i < 5; i++) {
          // 分页去数据库查询数据 这里可以去数据库查询每一页的数据
          List<DemoData> data = data();
          excelWriter.write(data, writeSheet);
      }
      // 千万别忘记finish 会帮忙关闭流
      excelWriter.finish();

      // 方法2 如果写到不同的sheet 同一个对象
      fileName = TestFileUtil.getPath() + "repeatedWrite" + System.currentTimeMillis() + ".xlsx";
      // 这里 指定文件
      excelWriter = EasyExcel.write(fileName, DemoData.class).build();
      // 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面
      for (int i = 0; i < 5; i++) {
          // 每次都要创建writeSheet 这里注意必须指定sheetNo
          writeSheet = EasyExcel.writerSheet(i, "模板").build();
          // 分页去数据库查询数据 这里可以去数据库查询每一页的数据
          List<DemoData> data = data();
          excelWriter.write(data, writeSheet);
      }
      // 千万别忘记finish 会帮忙关闭流
      excelWriter.finish();

      // 方法3 如果写到不同的sheet 不同的对象
      fileName = TestFileUtil.getPath() + "repeatedWrite" + System.currentTimeMillis() + ".xlsx";
      // 这里 指定文件
      excelWriter = EasyExcel.write(fileName).build();
      // 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面
      for (int i = 0; i < 5; i++) {
          // 每次都要创建writeSheet 这里注意必须指定sheetNo。这里注意DemoData.class 可以每次都变,我这里为了方便 所以用的同一个class 实际上可以一直变
          writeSheet = EasyExcel.writerSheet(i, "模板").head(DemoData.class).build();
          // 分页去数据库查询数据 这里可以去数据库查询每一页的数据
          List<DemoData> data = data();
          excelWriter.write(data, writeSheet);
      }
      // 千万别忘记finish 会帮忙关闭流
      excelWriter.finish();
  }

日期、数字或者自定义格式转换

excel示例

alibaba easyexcel 官方教程,附详细说明、例子、源码

对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Data
public class ConverterData {
    /**
     * 我想所有的 字符串起前面加上"自定义:"三个字
     */
    @ExcelProperty(value = "字符串标题", converter = CustomStringStringConverter.class)
    private String string;
    /**
     * 我想写到excel 用年月日的格式
     */
    @DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")
    @ExcelProperty("日期标题")
    private Date date;
    /**
     * 我想写到excel 用百分比表示
     */
    @NumberFormat("#.##%")
    @ExcelProperty(value = "数字标题")
    private Double doubleData;
}

代码

1
2
3
4
5
6
7
8
9
10
11
12
/**
 * 日期、数字或者自定义格式转换
 * <p>1. 创建excel对应的实体对象 参照{@link ConverterData}
 * <p>2. 使用{@link ExcelProperty}配合使用注解{@link DateTimeFormat}、{@link NumberFormat}或者自定义注解
 * <p>3. 直接写即可
 */
@Test
public void converterWrite() {
    String fileName = TestFileUtil.getPath() + "converterWrite" + System.currentTimeMillis() + ".xlsx";
    // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
    EasyExcel.write(fileName, ConverterData.class).sheet("模板").doWrite(data());
}

图片导出

excel示例

alibaba easyexcel 官方教程,附详细说明、例子、源码

对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Data
@ContentRowHeight(100)
@ColumnWidth(100 / 8)
public class ImageData {
    private File file;
    private InputStream inputStream;
    /**
     * 如果string类型 必须指定转换器,string默认转换成string
     */
    @ExcelProperty(converter = StringImageConverter.class)
    private String string;
    private byte[] byteArray;
    /**
     * 根据url导出
     *
     * @since 2.1.1
     */
    private URL url;
}

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
 * 图片导出
 * <p>
 * 1. 创建excel对应的实体对象 参照{@link ImageData}
 * <p>
 * 2. 直接写即可
 */
@Test
public void imageWrite() throws Exception {
    String fileName = TestFileUtil.getPath() + "imageWrite" + System.currentTimeMillis() + ".xlsx";
    // 如果使用流 记得关闭
    InputStream inputStream = null;
    try {
        List<ImageData> list = new ArrayList<ImageData>();
        ImageData imageData = new ImageData();
        list.add(imageData);
        String imagePath = TestFileUtil.getPath() + "converter" + File.separator + "img.jpg";
        // 放入五种类型的图片 实际使用只要选一种即可
        imageData.setByteArray(FileUtils.readFileToByteArray(new File(imagePath)));
        imageData.setFile(new File(imagePath));
        imageData.setString(imagePath);
        inputStream = FileUtils.openInputStream(new File(imagePath));
        imageData.setInputStream(inputStream);
        imageData.setUrl(new URL(
            "https://raw.githubusercontent.com/alibaba/easyexcel/master/src/test/resources/converter/img.jpg"));
        EasyExcel.write(fileName, ImageData.class).sheet().doWrite(list);
    } finally {
        if (inputStream != null) {
            inputStream.close();
        }
    }
}

根据模板写入

alibaba easyexcel 官方教程,附详细说明、例子、源码

 

对象

参照:对象

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
 * 根据模板写入
 * <p>1. 创建excel对应的实体对象 参照{@link IndexData}
 * <p>2. 使用{@link ExcelProperty}注解指定写入的列
 * <p>3. 使用withTemplate 写取模板
 * <p>4. 直接写即可
 */
@Test
public void templateWrite() {
    String templateFileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx";
    String fileName = TestFileUtil.getPath() + "templateWrite" + System.currentTimeMillis() + ".xlsx";
    // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
    EasyExcel.write(fileName, DemoData.class).withTemplate(templateFileName).sheet().doWrite(data());
}

列宽、行高

excel示例

alibaba easyexcel 官方教程,附详细说明、例子、源码

对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Data
@ContentRowHeight(10)
@HeadRowHeight(20)
@ColumnWidth(25)
public class WidthAndHeightData {
    @ExcelProperty("字符串标题")
    private String string;
    @ExcelProperty("日期标题")
    private Date date;
    /**
     * 宽度为50
     */
    @ColumnWidth(50)
    @ExcelProperty("数字标题")
    private Double doubleData;
}

代码

1
2
3
4
5
6
7
8
9
10
11
12
/**
 * 列宽、行高
 * <p>1. 创建excel对应的实体对象 参照{@link WidthAndHeightData}
 * <p>2. 使用注解{@link ColumnWidth}、{@link HeadRowHeight}、{@link ContentRowHeight}指定宽度或高度
 * <p>3. 直接写即可
 */
@Test
public void widthAndHeightWrite() {
    String fileName = TestFileUtil.getPath() + "widthAndHeightWrite" + System.currentTimeMillis() + ".xlsx";
    // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
    EasyExcel.write(fileName, WidthAndHeightData.class).sheet("模板").doWrite(data());
}

自定义样式

excel示例

alibaba easyexcel 官方教程,附详细说明、例子、源码

对象

参照:对象

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
 * 自定义样式
 * <p>1. 创建excel对应的实体对象 参照{@link DemoData}
 * <p>2. 创建一个style策略 并注册
 * <p>3. 直接写即可
 */
@Test
public void styleWrite() {
    String fileName = TestFileUtil.getPath() + "styleWrite" + System.currentTimeMillis() + ".xlsx";
    // 头的策略
    WriteCellStyle headWriteCellStyle = new WriteCellStyle();
    // 背景设置为红色
    headWriteCellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
    WriteFont headWriteFont = new WriteFont();
    headWriteFont.setFontHeightInPoints((short)20);
    headWriteCellStyle.setWriteFont(headWriteFont);
    // 内容的策略
    WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
    // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定
    contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
    // 背景绿色
    contentWriteCellStyle.setFillForegroundColor(IndexedColors.GREEN.getIndex());
    WriteFont contentWriteFont = new WriteFont();
    // 字体大小
    contentWriteFont.setFontHeightInPoints((short)20);
    contentWriteCellStyle.setWriteFont(contentWriteFont);
    // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
    HorizontalCellStyleStrategy horizontalCellStyleStrategy =
        new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);

    // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
    EasyExcel.write(fileName, DemoData.class).registerWriteHandler(horizontalCellStyleStrategy).sheet("模板")
        .doWrite(data());
}

合并单元格

excel示例

alibaba easyexcel 官方教程,附详细说明、例子、源码

对象

参照:对象

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
  * 合并单元格
  * <p>1. 创建excel对应的实体对象 参照{@link DemoData}
  * <p>2. 创建一个merge策略 并注册
  * <p>3. 直接写即可
  */
 @Test
 public void mergeWrite() {
     String fileName = TestFileUtil.getPath() + "mergeWrite" + System.currentTimeMillis() + ".xlsx";
     // 每隔2行会合并 把eachColumn 设置成 3 也就是我们数据的长度,所以就第一列会合并。当然其他合并策略也可以自己写
     LoopMergeStrategy loopMergeStrategy = new LoopMergeStrategy(2, 0);
     // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
     EasyExcel.write(fileName, DemoData.class).registerWriteHandler(loopMergeStrategy).sheet("模板")
         .doWrite(data());
 }

使用table去写入

excel示例

alibaba easyexcel 官方教程,附详细说明、例子、源码

对象

参照:对象

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
  * 使用table去写入
  * <p>1. 创建excel对应的实体对象 参照{@link DemoData}
  * <p>2. 然后写入table即可
  */
 @Test
 public void tableWrite() {
     String fileName = TestFileUtil.getPath() + "tableWrite" + System.currentTimeMillis() + ".xlsx";
     // 这里直接写多个table的案例了,如果只有一个 也可以直一行代码搞定,参照其他案例
     // 这里 需要指定写用哪个class去写
     ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build();
     // 把sheet设置为不需要头 不然会输出sheet的头 这样看起来第一个table 就有2个头了
     WriteSheet writeSheet = EasyExcel.writerSheet("模板").needHead(Boolean.FALSE).build();
     // 这里必须指定需要头,table 会继承sheet的配置,sheet配置了不需要,table 默认也是不需要
     WriteTable writeTable0 = EasyExcel.writerTable(0).needHead(Boolean.TRUE).build();
     WriteTable writeTable1 = EasyExcel.writerTable(1).needHead(Boolean.TRUE).build();
     // 第一次写入会创建头
     excelWriter.write(data(), writeSheet, writeTable0);
     // 第二次写如也会创建头,然后在第一次的后面写入数据
     excelWriter.write(data(), writeSheet, writeTable1);
     // 千万别忘记finish 会帮忙关闭流
     excelWriter.finish();
 }

动态头,实时生成头写入

excel示例

alibaba easyexcel 官方教程,附详细说明、例子、源码

对象

参照:对象

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/**
 * 动态头,实时生成头写入
 * <p>
 * 思路是这样子的,先创建List<String>头格式的sheet仅仅写入头,然后通过table 不写入头的方式 去写入数据
 *
 * <p>
 * 1. 创建excel对应的实体对象 参照{@link DemoData}
 * <p>
 * 2. 然后写入table即可
 */
@Test
public void dynamicHeadWrite() {
    String fileName = TestFileUtil.getPath() + "dynamicHeadWrite" + System.currentTimeMillis() + ".xlsx";
    EasyExcel.write(fileName)
        // 这里放入动态头
        .head(head()).sheet("模板")
        // 当然这里数据也可以用 List<List<String>> 去传入
        .doWrite(data());
}

private List<List<String>> head() {
    List<List<String>> list = new ArrayList<List<String>>();
    List<String> head0 = new ArrayList<String>();
    head0.add("字符串" + System.currentTimeMillis());
    List<String> head1 = new ArrayList<String>();
    head1.add("数字" + System.currentTimeMillis());
    List<String> head2 = new ArrayList<String>();
    head2.add("日期" + System.currentTimeMillis());
    list.add(head0);
    list.add(head1);
    list.add(head2);
    return list;
}

自动列宽(不太精确)

excel示例

alibaba easyexcel 官方教程,附详细说明、例子、源码

对象

1
2
3
4
5
6
7
8
9
@Data
public class LongestMatchColumnWidthData {
    @ExcelProperty("字符串标题")
    private String string;
    @ExcelProperty("日期标题很长日期标题很长日期标题很长很长")
    private Date date;
    @ExcelProperty("数字")
    private Double doubleData;
}

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
  * 自动列宽(不太精确)
  * <p>
  * 这个目前不是很好用,比如有数字就会导致换行。而且长度也不是刚好和实际长度一致。 所以需要精确到刚好列宽的慎用。 当然也可以自己参照
  * {@link LongestMatchColumnWidthStyleStrategy}重新实现.
  * <p>
  * poi 自带{@link SXSSFSheet#autoSizeColumn(int)} 对中文支持也不太好。目前没找到很好的算法。 有的话可以推荐下。
  *
  * <p>
  * 1. 创建excel对应的实体对象 参照{@link LongestMatchColumnWidthData}
  * <p>
  * 2. 注册策略{@link LongestMatchColumnWidthStyleStrategy}
  * <p>
  * 3. 直接写即可
  */
 @Test
 public void longestMatchColumnWidthWrite() {
     String fileName =
         TestFileUtil.getPath() + "longestMatchColumnWidthWrite" + System.currentTimeMillis() + ".xlsx";
     // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
     EasyExcel.write(fileName, LongestMatchColumnWidthData.class)
         .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).sheet("模板").doWrite(dataLong());
 }

 private List<LongestMatchColumnWidthData> dataLong() {
     List<LongestMatchColumnWidthData> list = new ArrayList<LongestMatchColumnWidthData>();
     for (int i = 0; i < 10; i++) {
         LongestMatchColumnWidthData data = new LongestMatchColumnWidthData();
         data.setString("测试很长的字符串测试很长的字符串测试很长的字符串" + i);
         data.setDate(new Date());
         data.setDoubleData(1000000000000.0);
         list.add(data);
     }
     return list;
 }

自定义拦截器(上面几点都不符合但是要对单元格进行操作的参照这个)

excel示例

alibaba easyexcel 官方教程,附详细说明、例子、源码

对象

参照:对象

定义拦截器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
 * 自定义拦截器。对第一行第一列的头超链接到:https://github.com/alibaba/easyexcel
 *
 * @author Jiaju Zhuang
 */
public class CustomCellWriteHandler implements CellWriteHandler {

    private static final Logger LOGGER = LoggerFactory.getLogger(CustomCellWriteHandler.class);

    @Override
    public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
        Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {

    }

    @Override
    public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell,
        Head head, Integer relativeRowIndex, Boolean isHead) {

    }

    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
        List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        // 这里可以对cell进行任何操作
        LOGGER.info("第{}行,第{}列写入完成。", cell.getRowIndex(), cell.getColumnIndex());
        if (isHead && cell.getColumnIndex() == 0) {
            CreationHelper createHelper = writeSheetHolder.getSheet().getWorkbook().getCreationHelper();
            Hyperlink hyperlink = createHelper.createHyperlink(HyperlinkType.URL);
            hyperlink.setAddress("https://github.com/alibaba/easyexcel");
            cell.setHyperlink(hyperlink);
        }
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
 * 自定义拦截器.对第一列第一行和第二行的数据新增下拉框,显示 测试1 测试2
 *
 * @author Jiaju Zhuang
 */
public class CustomSheetWriteHandler implements SheetWriteHandler {

    private static final Logger LOGGER = LoggerFactory.getLogger(CustomSheetWriteHandler.class);

    @Override
    public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {

    }

    @Override
    public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
        LOGGER.info("第{}个Sheet写入成功。", writeSheetHolder.getSheetNo());

        // 区间设置 第一列第一行和第二行的数据。由于第一行是头,所以第一、二行的数据实际上是第二三行
        CellRangeAddressList cellRangeAddressList = new CellRangeAddressList(1, 2, 0, 0);
        DataValidationHelper helper = writeSheetHolder.getSheet().getDataValidationHelper();
        DataValidationConstraint constraint = helper.createExplicitListConstraint(new String[] {"测试1", "测试2"});
        DataValidation dataValidation = helper.createValidation(constraint, cellRangeAddressList);
        writeSheetHolder.getSheet().addValidationData(dataValidation);
    }
}

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
 * 下拉,超链接等自定义拦截器(上面几点都不符合但是要对单元格进行操作的参照这个)
 * <p>
 * demo这里实现2点。1. 对第一行第一列的头超链接到:https://github.com/alibaba/easyexcel 2. 对第一列第一行和第二行的数据新增下拉框,显示 测试1 测试2
 * <p>
 * 1. 创建excel对应的实体对象 参照{@link DemoData}
 * <p>
 * 2. 注册拦截器 {@link CustomCellWriteHandler} {@link CustomSheetWriteHandler}
 * <p>
 * 2. 直接写即可
 */
@Test
public void customHandlerWrite() {
    String fileName = TestFileUtil.getPath() + "customHandlerWrite" + System.currentTimeMillis() + ".xlsx";
    // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
    EasyExcel.write(fileName, DemoData.class).registerWriteHandler(new CustomSheetWriteHandler())
        .registerWriteHandler(new CustomCellWriteHandler()).sheet("模板").doWrite(data());
}

不创建对象的写

excel示例

alibaba easyexcel 官方教程,附详细说明、例子、源码

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/**
     * 不创建对象的写
     */
    @Test
    public void noModleWrite() {
        // 写法1
        String fileName = TestFileUtil.getPath() + "noModleWrite" + System.currentTimeMillis() + ".xlsx";
        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        EasyExcel.write(fileName).head(head()).sheet("模板").doWrite(dataList());
    }

 private List<List<String>> head() {
        List<List<String>> list = new ArrayList<List<String>>();
        List<String> head0 = new ArrayList<String>();
        head0.add("字符串" + System.currentTimeMillis());
        List<String> head1 = new ArrayList<String>();
        head1.add("数字" + System.currentTimeMillis());
        List<String> head2 = new ArrayList<String>();
        head2.add("日期" + System.currentTimeMillis());
        list.add(head0);
        list.add(head1);
        list.add(head2);
        return list;
    }

    private List<List<Object>> dataList() {
        List<List<Object>> list = new ArrayList<List<Object>>();
        for (int i = 0; i < 10; i++) {
            List<Object> data = new ArrayList<Object>();
            data.add("字符串" + i);
            data.add(new Date());
            data.add(0.56);
            list.add(data);
        }
        return list;
    }

web中的写

示例代码

DEMO代码地址:https://github.com/alibaba/easyexcel/blob/master/src/test/java/com/alibaba/easyexcel/test/demo/web/WebTest.java

对象

参照:对象 就是名称变了下

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
 * 文件下载(失败了会返回一个有部分数据的Excel)
 * <p>
 * 1. 创建excel对应的实体对象 参照{@link DownloadData}
 * <p>
 * 2. 设置返回的 参数
 * <p>
 * 3. 直接写,这里注意,finish的时候会自动关闭OutputStream,当然你外面再关闭流问题不大
 */
@GetMapping("download")
public void download(HttpServletResponse response) throws IOException {
    // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
    response.setContentType("application/vnd.ms-excel");
    response.setCharacterEncoding("utf-8");
    // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
    String fileName = URLEncoder.encode("测试", "UTF-8");
    response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
    EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet("模板").doWrite(data());
}

web中的写并且失败的时候返回json

对象

参照:对象 就是名称变了下

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
     * 文件下载并且失败的时候返回json(默认失败了会返回一个有部分数据的Excel)
     *
     * @since 2.1.1
     */
    @GetMapping("downloadFailedUsingJson")
    public void downloadFailedUsingJson(HttpServletResponse response) throws IOException {
        // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
        try {
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("测试", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            // 这里需要设置不关闭流
            EasyExcel.write(response.getOutputStream(), DownloadData.class).autoCloseStream(Boolean.FALSE).sheet("模板")
                .doWrite(data());
        } catch (Exception e) {
            // 重置response
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            Map<String, String> map = new HashMap<String, String>();
            map.put("status", "failure");
            map.put("message", "下载文件失败" + e.getMessage());
            response.getWriter().println(JSON.toJSONString(map));
        }
    }