- Excel和Java对象映射的实体类注解
- 注解位置
- @ExcelProperty(用于匹配excel和实体类的匹配)
- @ExcelIgnore(忽略字段)
- @ExcelIgnoreUnannotated(不参与匹配)
- @DateTimeFormat(日期转换)
- @NumberFormat(数字转换)
- @ColumnWith(列宽)
- @ContentFontStyle(单元格字体样式)
- @ContentLoopMerge(合并单元格)
- @OnceAbsoluteMerge(指定坐标合并单元格)
- @ContentRowHeight(行高)
- @ContentStyle(内容样式)
- @HeadFontStyle(标题字体样式)
- @HeadRowHeight(标题行高)
- @HeadStyle(标题样式)
- 写入Excel
Excel和Java对象映射的实体类注解
Excel可以看作是一张表,每一列都是一个字段,所以一行数据其实可以映射成一个java对象。
而整个Excel表的数据,就是一个List
怎么让Excel里面的列和Java类字段进行匹配呢?就需要用到一些注解。
注解位置


根据上面的Excel例子1,我们创建一个Java对象类。
加上一些注解,让这个java类和excel匹配。更多注解看下面的
@Data@EqualsAndHashCodepublic class DemoData {@ExcelProperty("字符串标题")private String string;@ExcelProperty("日期标题")private Date date;@ExcelProperty("数字标题")private Double doubleData;/*** 忽略这个字段*/@ExcelIgnoreprivate String ignore;}
public class ComplexHeadData {@ExcelProperty({"主标题", "字符串标题"})private String string;@ExcelProperty({"主标题", "日期标题"})private Date date;@ExcelProperty({"主标题", "数字标题"})private Double doubleData;}
@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个字符。
public class ImeiEncrypt {@ColumnWidth(value = 18)private String imei;}
@ContentFontStyle(单元格字体样式)
用于设置单元格内容字体格式的注解
| 参数 | 含义 |
|---|---|
| fontName | 字体名称 |
| fontHeightInPoints | 字体高度 |
| italic | 是否斜体 |
| strikeout | 是否设置删除水平线 |
| color | 字体颜色 |
| typeOffset | 偏移量 |
| underline | 下划线 |
| bold | 是否加粗 |
| charset | 编码格式 |
@ContentLoopMerge(合并单元格)
用于设置合并单元格的注解
| 参数 | 含义 |
|---|---|
| eachRow | 每隔多少行合并单元格 |
| columnExtend | 对列进行合并,合并多少列 |
public class DemoMergeData {//这一列 每隔2行 合并单元格@ContentLoopMerge(eachRow = 2)@ExcelProperty("字符串标题")private String string;}
@OnceAbsoluteMerge(指定坐标合并单元格)
作用在类上,合并一次单元格,指定坐标
// 将第6-7行的2-3列合并成一个单元格@OnceAbsoluteMerge(firstRowIndex = 5, lastRowIndex = 6, firstColumnIndex = 1, lastColumnIndex = 2)public class DemoMergeData {// 这一列 每隔2行 合并单元格@ContentLoopMerge(eachRow = 2)@ExcelProperty("字符串标题")private String string;}
@ContentRowHeight(行高)
@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(标题行高)
@HeadStyle(标题样式)
写入Excel
最简单的写
/*** 最简单的写* <p>* 1. 创建excel对应的实体对象 参照{@link DemoData}* <p>* 2. 直接写即可*/@Testpublic void simpleWrite() {// 注意 simpleWrite在数据量不大的情况下可以使用(5000以内,具体也要看实际情况),数据量大参照 重复多次写入// 写法1 JDK8+// since: 3.0.0-beta1String fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭// 如果这里想使用03 则 传入excelType参数即可EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(() -> {// 分页查询数据return data();});// 写法2fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭// 如果这里想使用03 则 传入excelType参数即可EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());// 写法3fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";// 这里 需要指定写用哪个class去写try (ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build()) {WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();excelWriter.write(data(), writeSheet);}}
根据参数只导出指定列
/*** 根据参数只导出指定列* <p>* 1. 创建excel对应的实体对象 参照{@link DemoData}* <p>* 2. 根据自己或者排除自己需要的列* <p>* 3. 直接写即可** @since 2.1.1*/@Testpublic void excludeOrIncludeWrite() {String fileName = TestFileUtil.getPath() + "excludeOrIncludeWrite" + System.currentTimeMillis() + ".xlsx";// 这里需要注意 在使用ExcelProperty注解的使用,如果想不空列则需要加入order字段,而不是index,order会忽略空列,然后继续往后,而index,不会忽略空列,在第几列就是第几列。// 根据用户传入字段 假设我们要忽略 dateSet<String> excludeColumnFieldNames = new HashSet<>();excludeColumnFieldNames.add("date");// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, DemoData.class).excludeColumnFieldNames(excludeColumnFieldNames).sheet("模板").doWrite(data());fileName = TestFileUtil.getPath() + "excludeOrIncludeWrite" + System.currentTimeMillis() + ".xlsx";// 根据用户传入字段 假设我们只要导出 dateSet<String> includeColumnFieldNames = new HashSet<>();includeColumnFieldNames.add("date");// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, DemoData.class).includeColumnFieldNames(includeColumnFieldNames).sheet("模板").doWrite(data());}
多次重复写入
/*** 重复多次写入* <p>* 1. 创建excel对应的实体对象 参照{@link ComplexHeadData}* <p>* 2. 使用{@link ExcelProperty}注解指定复杂的头* <p>* 3. 直接调用二次写入即可*/@Testpublic void repeatedWrite() {// 方法1: 如果写到同一个sheetString fileName = TestFileUtil.getPath() + "repeatedWrite" + System.currentTimeMillis() + ".xlsx";// 这里 需要指定写用哪个class去写try (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);}}// 方法2: 如果写到不同的sheet 同一个对象fileName = TestFileUtil.getPath() + "repeatedWrite" + System.currentTimeMillis() + ".xlsx";// 这里 指定文件try (ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build()) {// 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面for (int i = 0; i < 5; i++) {// 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样WriteSheet writeSheet = EasyExcel.writerSheet(i, "模板" + i).build();// 分页去数据库查询数据 这里可以去数据库查询每一页的数据List<DemoData> data = data();excelWriter.write(data, writeSheet);}}// 方法3 如果写到不同的sheet 不同的对象fileName = TestFileUtil.getPath() + "repeatedWrite" + System.currentTimeMillis() + ".xlsx";// 这里 指定文件try (ExcelWriter excelWriter = EasyExcel.write(fileName).build()) {// 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面for (int i = 0; i < 5; i++) {// 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样。这里注意DemoData.class 可以每次都变,我这里为了方便 所以用的同一个class// 实际上可以一直变WriteSheet writeSheet = EasyExcel.writerSheet(i, "模板" + i).head(DemoData.class).build();// 分页去数据库查询数据 这里可以去数据库查询每一页的数据List<DemoData> data = data();excelWriter.write(data, writeSheet);}}}
根据模板写入
/*** 根据模板写入* <p>* 1. 创建excel对应的实体对象 参照{@link IndexData}* <p>* 2. 使用{@link ExcelProperty}注解指定写入的列* <p>* 3. 使用withTemplate 写取模板* <p>* 4. 直接写即可*/@Testpublic 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());}
动态的标题头写入
/*** 动态头,实时生成头写入* <p>* 思路是这样子的,先创建List<String>头格式的sheet仅仅写入头,然后通过table 不写入头的方式 去写入数据** <p>* 1. 创建excel对应的实体对象 参照{@link DemoData}* <p>* 2. 然后写入table即可*/@Testpublic void dynamicHeadWrite() {String fileName = TestFileUtil.getPath() + "dynamicHeadWrite" + System.currentTimeMillis() + ".xlsx";EasyExcel.write(fileName)// 这里放入动态头,head方法返回List<String>,装的标题.head(head()).sheet("模板")//具体的数据.doWrite(data());}
