github地址
easyexcel官网

Excel和Java对象映射的实体类注解

Excel可以看作是一张表,每一列都是一个字段,所以一行数据其实可以映射成一个java对象。
而整个Excel表的数据,就是一个List
怎么让Excel里面的列和Java类字段进行匹配呢?就需要用到一些注解。

注解位置

image.png

image.png
根据上面的Excel例子1,我们创建一个Java对象类。
加上一些注解,让这个java类和excel匹配。更多注解看下面的

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

@ExcelProperty(用于匹配excel和实体类的匹配)

参数如下。
上面的例子就指定了value。

名称 默认值 描述
value 用于匹配excel中的头,必须全匹配,如果有多行头,会匹配最后一行头
order Integer.MAX_VALUE 优先级高于value,会根据order的顺序来匹配实体和excel中数据的顺序
index -1 优先级高于value和order,会根据index直接指定到excel中具体的哪一列
converter 自动选择 指定当前字段用什么转换器,默认会自动选择。读的情况下只要实现com.alibaba.excel.converters.Converter#convertToJavaData(com.alibaba.excel.converters.ReadConverterContext<?>)方法即可

@ExcelIgnore(忽略字段)

默认所有字段都会和excel去匹配,加了这个注解会忽略该字段

@ExcelIgnoreUnannotated(不参与匹配)

默认不加ExcelProperty的注解的都会参与读写,加了这个注解后,没加ExcelProperty的字段就不会参与

@DateTimeFormat(日期转换)

日期转换,用String去接收excel日期格式的数据会调用这个注解,参数如下:

名称 默认值 描述
value 参照java.text.SimpleDateFormat书写即可
use1904windowing 自动选择 excel中时间是存储1900年起的一个双精度浮点数,但是有时候默认开始日期是1904,所以设置这个值改成默认1904年开始

@NumberFormat(数字转换)

数字转换,用String去接收excel数字格式的数据会调用这个注解。

名称 默认值 描述
value 参照java.text.DecimalFormat书写即可
roundingMode RoundingMode.HALF_UP 格式化的时候设置舍入模式

@ColumnWith(列宽)

用于设置列宽度的注解,注解中只有一个参数value,value的单位是字符长度,最大可以设置255个字符,因为一个excel单元格最大可以写入的字符个数就是255个字符。

  1. public class ImeiEncrypt {
  2. @ColumnWidth(value = 18)
  3. private String imei;
  4. }

@ContentFontStyle(单元格字体样式)

用于设置单元格内容字体格式的注解

参数 含义
fontName 字体名称
fontHeightInPoints 字体高度
italic 是否斜体
strikeout 是否设置删除水平线
color 字体颜色
typeOffset 偏移量
underline 下划线
bold 是否加粗
charset 编码格式

@ContentLoopMerge(合并单元格)

用于设置合并单元格的注解

参数 含义
eachRow 每隔多少行合并单元格
columnExtend 对列进行合并,合并多少列
  1. public class DemoMergeData {
  2. //这一列 每隔2行 合并单元格
  3. @ContentLoopMerge(eachRow = 2)
  4. @ExcelProperty("字符串标题")
  5. private String string;
  6. }

@OnceAbsoluteMerge(指定坐标合并单元格)

作用在类上,合并一次单元格,指定坐标

  1. // 将第6-7行的2-3列合并成一个单元格
  2. @OnceAbsoluteMerge(firstRowIndex = 5, lastRowIndex = 6, firstColumnIndex = 1, lastColumnIndex = 2)
  3. public class DemoMergeData {
  4. // 这一列 每隔2行 合并单元格
  5. @ContentLoopMerge(eachRow = 2)
  6. @ExcelProperty("字符串标题")
  7. private String string;
  8. }

@ContentRowHeight(行高)

用于设置行高,-1代表自动行高

@ContentStyle(内容样式)

设置内容格式注解

参数 含义
dataFormat 日期格式
hidden 设置单元格使用此样式隐藏
locked 设置单元格使用此样式锁定
quotePrefix 在单元格前面增加```符号,数字或者公式将以字符串形式展示
horizontalAlignment 设置是否水平居中
wrapped 设置文本是否换行。将此标志设置为true,通过在多行上显示使单元格中所有内容可见
verticalAlignment 设置是否垂直居中
rotation 设置单元格中文本的旋转角度。03版本的Excel旋转角度区间为-90~90,07版本的Excel旋转角度区间为0~180
indent 设置单元格中缩进文本的空格数
borderLeft 设置左边框样式
borderRight 设置右边框样式
borderTop 设置上边框样式
borderBottom 设置下边框样式
leftBorderColor 设置左边框颜色
rightBorderColor 设置右边框颜色
topBorderColor 设置上边框颜色
bottomBorderColor 设置下边框颜色
fillPatternType 设置填充类型
fillBackgroundColor 设置背景色
fillForegroundColor 设置前景色
shrinkToFit 设置自动单元格自动大小

@HeadFontStyle(标题字体样式)

用于定制标题字体格式

参数 含义
fontName 设置字体名称
fontHeightInPoints 设置字体高度
italic 设置字体是否斜体
strikeout 是否设置删除线
color 设置字体颜色
typeOffset 设置偏移量
underline 设置下划线
charset 设置字体编码
bold 设置字体是否家畜

@HeadRowHeight(标题行高)

设置标题行高,-1代表自动行高

@HeadStyle(标题样式)

设置标题样式,具体参数见上面的@ContentStyle

写入Excel

最简单的写

  1. /**
  2. * 最简单的写
  3. * <p>
  4. * 1. 创建excel对应的实体对象 参照{@link DemoData}
  5. * <p>
  6. * 2. 直接写即可
  7. */
  8. @Test
  9. public void simpleWrite() {
  10. // 注意 simpleWrite在数据量不大的情况下可以使用(5000以内,具体也要看实际情况),数据量大参照 重复多次写入
  11. // 写法1 JDK8+
  12. // since: 3.0.0-beta1
  13. String fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";
  14. // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
  15. // 如果这里想使用03 则 传入excelType参数即可
  16. EasyExcel.write(fileName, DemoData.class)
  17. .sheet("模板")
  18. .doWrite(() -> {
  19. // 分页查询数据
  20. return data();
  21. });
  22. // 写法2
  23. fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";
  24. // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
  25. // 如果这里想使用03 则 传入excelType参数即可
  26. EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());
  27. // 写法3
  28. fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";
  29. // 这里 需要指定写用哪个class去写
  30. try (ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build()) {
  31. WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
  32. excelWriter.write(data(), writeSheet);
  33. }
  34. }

根据参数只导出指定列

  1. /**
  2. * 根据参数只导出指定列
  3. * <p>
  4. * 1. 创建excel对应的实体对象 参照{@link DemoData}
  5. * <p>
  6. * 2. 根据自己或者排除自己需要的列
  7. * <p>
  8. * 3. 直接写即可
  9. *
  10. * @since 2.1.1
  11. */
  12. @Test
  13. public void excludeOrIncludeWrite() {
  14. String fileName = TestFileUtil.getPath() + "excludeOrIncludeWrite" + System.currentTimeMillis() + ".xlsx";
  15. // 这里需要注意 在使用ExcelProperty注解的使用,如果想不空列则需要加入order字段,而不是index,order会忽略空列,然后继续往后,而index,不会忽略空列,在第几列就是第几列。
  16. // 根据用户传入字段 假设我们要忽略 date
  17. Set<String> excludeColumnFieldNames = new HashSet<>();
  18. excludeColumnFieldNames.add("date");
  19. // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
  20. EasyExcel.write(fileName, DemoData.class).excludeColumnFieldNames(excludeColumnFieldNames).sheet("模板")
  21. .doWrite(data());
  22. fileName = TestFileUtil.getPath() + "excludeOrIncludeWrite" + System.currentTimeMillis() + ".xlsx";
  23. // 根据用户传入字段 假设我们只要导出 date
  24. Set<String> includeColumnFieldNames = new HashSet<>();
  25. includeColumnFieldNames.add("date");
  26. // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
  27. EasyExcel.write(fileName, DemoData.class).includeColumnFieldNames(includeColumnFieldNames).sheet("模板")
  28. .doWrite(data());
  29. }

多次重复写入

  1. /**
  2. * 重复多次写入
  3. * <p>
  4. * 1. 创建excel对应的实体对象 参照{@link ComplexHeadData}
  5. * <p>
  6. * 2. 使用{@link ExcelProperty}注解指定复杂的头
  7. * <p>
  8. * 3. 直接调用二次写入即可
  9. */
  10. @Test
  11. public void repeatedWrite() {
  12. // 方法1: 如果写到同一个sheet
  13. String fileName = TestFileUtil.getPath() + "repeatedWrite" + System.currentTimeMillis() + ".xlsx";
  14. // 这里 需要指定写用哪个class去写
  15. try (ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build()) {
  16. // 这里注意 如果同一个sheet只要创建一次
  17. WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
  18. // 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来
  19. for (int i = 0; i < 5; i++) {
  20. // 分页去数据库查询数据 这里可以去数据库查询每一页的数据
  21. List<DemoData> data = data();
  22. excelWriter.write(data, writeSheet);
  23. }
  24. }
  25. // 方法2: 如果写到不同的sheet 同一个对象
  26. fileName = TestFileUtil.getPath() + "repeatedWrite" + System.currentTimeMillis() + ".xlsx";
  27. // 这里 指定文件
  28. try (ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build()) {
  29. // 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面
  30. for (int i = 0; i < 5; i++) {
  31. // 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样
  32. WriteSheet writeSheet = EasyExcel.writerSheet(i, "模板" + i).build();
  33. // 分页去数据库查询数据 这里可以去数据库查询每一页的数据
  34. List<DemoData> data = data();
  35. excelWriter.write(data, writeSheet);
  36. }
  37. }
  38. // 方法3 如果写到不同的sheet 不同的对象
  39. fileName = TestFileUtil.getPath() + "repeatedWrite" + System.currentTimeMillis() + ".xlsx";
  40. // 这里 指定文件
  41. try (ExcelWriter excelWriter = EasyExcel.write(fileName).build()) {
  42. // 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面
  43. for (int i = 0; i < 5; i++) {
  44. // 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样。这里注意DemoData.class 可以每次都变,我这里为了方便 所以用的同一个class
  45. // 实际上可以一直变
  46. WriteSheet writeSheet = EasyExcel.writerSheet(i, "模板" + i).head(DemoData.class).build();
  47. // 分页去数据库查询数据 这里可以去数据库查询每一页的数据
  48. List<DemoData> data = data();
  49. excelWriter.write(data, writeSheet);
  50. }
  51. }
  52. }

根据模板写入

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

动态的标题头写入

  1. /**
  2. * 动态头,实时生成头写入
  3. * <p>
  4. * 思路是这样子的,先创建List<String>头格式的sheet仅仅写入头,然后通过table 不写入头的方式 去写入数据
  5. *
  6. * <p>
  7. * 1. 创建excel对应的实体对象 参照{@link DemoData}
  8. * <p>
  9. * 2. 然后写入table即可
  10. */
  11. @Test
  12. public void dynamicHeadWrite() {
  13. String fileName = TestFileUtil.getPath() + "dynamicHeadWrite" + System.currentTimeMillis() + ".xlsx";
  14. EasyExcel.write(fileName)
  15. // 这里放入动态头,head方法返回List<String>,装的标题
  16. .head(head()).sheet("模板")
  17. //具体的数据
  18. .doWrite(data());
  19. }