1. 通用实体类
public class User {
@ExcelIgnore
private String id;
@ExcelProperty("用户名称")
private String userName;
@ExcelProperty("用户密码")
private String password;
@ExcelProperty("用户生日")
private String birthday;
@ExcelProperty("用户性别")
private Integer sex;
}
2. 导出
2.1. 导出 -- 列宽策略 && 指定导出排除的字段
即导出用户名称,用户密码,用户生日,用户性别字段。
public void exportData(HttpServletResponse response) throws IOException {
//设置不需要的字段
Set<String> excludedFields = new HashSet<>();
excludedFields.add("password");
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
//encode防止中文乱码,与easyexcel无关
String fileName = URLEncoder.encode("用户指定不需要导出字段模板测试","UTF-8").replaceAll("\\+", "%20");
response.addHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
//防止获取不到文件名称
response.addHeader("Access-Control-Expose-Headers", "Content-disposition");
//写到第一个sheet,文件流自动关闭
//users为自己数据库的查询结果集,类型为List<?>
EasyExcel.write(response.getOutputStream(), User.class)
.sheet("模板")
//列宽策略 宽25
.registerWriteHandler(new SimpleColumnWidthStyleStrategy(25))
//排除不需要的字段
.excludeColumnFiledNames(excludedFields)
// 写数据
.doWrite(users);
}
结果:
- 仅有列宽策略
- 列宽策略 && 排除字段(密码)
2.2. 导出 -- 指定写入的列
public class User {
@ExcelIgnore
private String id;
@ExcelProperty(value = "用户名称",index = 0)
private String userName;
@ExcelProperty(value = "用户密码",index = 1)
private String password;
@ExcelProperty(value = "用户生日",index = 5)
private String birthday;
@ExcelProperty(value = "用户性别",index = 2)
private Integer sex;
}
通过 index 来指定写入到哪列,导出代码不变。
结果:
2.3. 导出 -- 复杂头写入
将用户名称、用户密码、用户生日设为用户的基本信息
用户性别设为用户的个人信息。
public class User {
@ExcelIgnore
private String id;
@ExcelProperty(value = {"用户基本信息","用户名称"})
private String userName;
@ExcelProperty(value = {"用户基本信息","用户密码"})
private String password;
@ExcelProperty(value = {"用户基本信息","用户生日"})
private String birthday;
@ExcelProperty(value = {"用户个人信息","用户性别"})
private Integer sex;
}
其他代码正常写,只需修改实体类。
结果:
2.4. 导出 -- 写入单个或多个 sheet(一个对象写入多个 sheet,不同对象写入不同 sheet)
2.4.1. 多个相同的对象写入一个 sheet
业务场景:假设表中数据存在 100 条,分页查询一次只返回 20 条,现在需要将表中数据全部写入到 excel 的一个 sheet 中。
实现:
- 前端可以添加 boolean 类型的 page 字段,true 代表后端开启 pagehelper 分页,false 代表不开启。(最优)
- 后端循环插入。(官网使用的此方式)
实现 2 后端循环插入:
public void exportAllData(HttpServletResponse response) throws Exception {
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
//encode防止中文乱码,与easyexcel无关
String fileName = URLEncoder.encode("用户分页插入模板","UTF-8").replaceAll("\\+", "%20");
response.addHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
//防止获取不到文件名称
response.addHeader("Access-Control-Expose-Headers", "Content-disposition");
//模拟查询所有数据分页场景
//循环里为模拟数据方法,每个业务不同,无需管理
List<User> allData = new ArrayList<>();
for (int i = 0; i < 5; i++) {
init();
allData.addAll(users);
}
EasyExcel.write(response.getOutputStream(), User.class)
.sheet("模板")
.doWrite(allData);
}
结果:
2.4.2. 多个相同的对象写入不同的 sheet
业务场景:假设表中数据存在 100 条,分页查询一次只返回 20 条,需要将一次分页查询的结果写入到一个 sheet 中,可能存在多个 sheet
实现:
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
//encode防止中文乱码,与easyexcel无关
String fileName = URLEncoder.encode("用户分页插入模板","UTF-8").replaceAll("\\+", "%20");
response.addHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
//防止获取不到文件名称
response.addHeader("Access-Control-Expose-Headers", "Content-disposition");
ExcelWriter writer = EasyExcel.write(response.getOutputStream(), User.class).build();
//模拟数据不用管
init();
//假设总共需要5个sheet页,每页3条数据
for (int i = 0; i < 5; i++) {
//创建sheet时,必须指定编号和名称 并且 sheet名称必须不一样
WriteSheet sheet = EasyExcel.writerSheet(i + 1, "模板" + (i + 1)).build();
writer.write(users,sheet);
}
// 这边一定要finish,否则导出有问题
writer.finish();
结果:
2.4.3. 多个不同的对象写入到不同的 sheet 中
业务场景:假设有三个查询结果集,需要分别写入到不同的 sheet 中
实现: 就是在 ii.多个相同的对象写入不同的 sheet 中 代码的 13 ~ 17 行进行修改即可。
2.5. 导出 -- 日期、数字或者自定义格式转换。
业务场景:假设在数据库中性别存的是枚举值,但要求输出到 excel 中为男或女....
2.5.1. 实体类
public class People {
@ExcelProperty(value = "用户名称",converter = PeopleNameConvert.class,index = 0)
private String name;
/**
* 1:男 0: 女
*/
@ExcelProperty(value = "用户性别",converter = SexConvert.class,index = 1)
private Integer sex;
/**
* 用百分比表示
*/
@NumberFormat("#.##%")
@ExcelProperty(value = "余额",index = 2)
private Double balance;
@DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")
@ExcelProperty(value = "创建时间",index = 3)
private Date createdTime;
}
2.5.2. PeopleNameConvert
public class PeopleNameConvert implements Converter<String> {
@Override
public Class supportJavaTypeKey() {
return String.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
@Override
public String convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
return cellData.getStringValue() + "多加两个字";
}
@Override
public CellData convertToExcelData(String value, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
return new CellData(value + "少加两个字");
}
}
2.5.3. SexConvert
public class SexConvert implements Converter<Integer> {
@Override
public Class supportJavaTypeKey() {
return Integer.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
@Override
public Integer convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
return "男".equals(cellData.getStringValue()) ? 1 : 0;
}
@Override
public CellData convertToExcelData(Integer value, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
return new CellData(value.equals(1) ? "男" : "女");
}
}
2.5.4. 导出代码
public void exportAllData4(HttpServletResponse response) throws Exception {
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
//encode防止中文乱码,与easyexcel无关
String fileName = URLEncoder.encode("用户格式转换模板","UTF-8").replaceAll("\\+", "%20");
response.addHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
//防止获取不到文件名称
response.addHeader("Access-Control-Expose-Headers", "Content-disposition");
//模拟数据不用管
init2();
EasyExcel.write(response.getOutputStream(), People.class).sheet("模板").doWrite(peoples);
}
结果:
2.6. 导出 -- 图片
业务场景:需要导出图片到 excel 中
2.6.1. 实体类
@NoArgsConstructor
@AllArgsConstructor
@Data
@ContentRowHeight(100)
@ColumnWidth(100 / 8)
public class ImageData {
@ExcelProperty(value = "名称")
@ColumnWidth(20)
private String fileName;
@ExcelProperty(value = "图片")
@ColumnWidth(20)
private URL imagePath;
}
2.6.2. 导出代码
public void exportImage(HttpServletResponse response) throws Exception {
//初始化从数据库查的数据,不用管
init3();
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
//encode防止中文乱码,与easyexcel无关
String fileName = URLEncoder.encode("图片导出测试","UTF-8").replaceAll("\\+", "%20");
response.addHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
//防止获取不到文件名称
response.addHeader("Access-Control-Expose-Headers", "Content-disposition");
EasyExcel.write(response.getOutputStream(), ImageData.class).sheet("模板").doWrite(images);
}
2.6.3. 测试
2.7. 导出 -- 超链接、备注、指定单元格多个样式
2.7.1. 实体类
@Data
@EqualsAndHashCode
public class WriteCellDemoData {
/**
* 超链接
*
* @since 3.0.0-beta1
*/
private WriteCellData<String> hyperlink;
/**
* 备注
*
* @since 3.0.0-beta1
*/
private WriteCellData<String> commentData;
/**
* 指定单元格的样式。当然样式 也可以用注解等方式。
*
* @since 3.0.0-beta1
*/
private WriteCellData<String> writeCellStyle;
}
2.7.2. 导出代码
public void exportCellData(HttpServletResponse response) throws IOException {
WriteCellDemoData cellDemoData = new WriteCellDemoData();
//超链接
WriteCellData<String> cellData = new WriteCellData<>("百度");
cellDemoData.setHyperlink(cellData);
HyperlinkData hyperlinkData = new HyperlinkData();
hyperlinkData.setAddress("https://www.baidu.com/");
hyperlinkData.setHyperlinkType(HyperlinkData.HyperlinkType.URL);
cellData.setHyperlinkData(hyperlinkData);
//设置备注
cellData = new WriteCellData<>("单元格显示的信息");
cellDemoData.setCommentData(cellData);
CommentData commentData = new CommentData();
cellData.setCommentData(commentData);
commentData.setAuthor("gsx");
commentData.setRichTextStringData(new RichTextStringData("这是一条备注"));
// 备注的默认大小是按照单元格的大小 这里想调整到4个单元格那么大 所以向后 向下 各额外占用了一个单元格
commentData.setRelativeLastColumnIndex(1);
commentData.setRelativeLastRowIndex(1);
//设置单个单元格的样式
cellData = new WriteCellData<>("单元格样式");
cellData.setType(CellDataTypeEnum.STRING);
cellDemoData.setWriteCellStyle(cellData);
WriteCellStyle style = new WriteCellStyle();
cellData.setWriteCellStyle(style);
//设置填充样式
style.setFillPatternType(FillPatternType.BIG_SPOTS);
//设置背景颜色
style.setFillForegroundColor(IndexedColors.GREEN.getIndex());
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
//encode防止中文乱码,与easyexcel无关
String fileName = URLEncoder.encode("图片导出测试","UTF-8").replaceAll("\\+", "%20");
response.addHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
//防止获取不到文件名称
response.addHeader("Access-Control-Expose-Headers", "Content-disposition");
EasyExcel.write(response.getOutputStream(),WriteCellDemoData.class)
.sheet()
.doWrite(Arrays.asList(cellDemoData));
}
2.8. 列宽、行高
@ContentRowHeight: 设置 row 高度,不包含表头,标记在 类上。
@HeadRowHeight(int):设置表头高度,标记在类上。
@ColumnWidth(int): 设置列宽
2.9. 注解自定义样式
@HeadStyle:设置标题样式
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 设置字体是否加粗
@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 设置自动单元格自动大小
@ContentFontStyle:内容字体样式
参数:
fontName 字体名称
fontHeightInPoints 字体高度
italic 是否斜体
strikeout 是否设置删除水平线
color 字体颜色
typeOffset 偏移量
underline 下划线
bold 是否加粗
charset 编码格式
2.10. 合并单元格
// 这一列 每隔2行 合并单元格 加在属性上
@ContentLoopMerge(eachRow = 2)
// 将第6-7行的2-3列合并成一个单元格 加在类上
@OnceAbsoluteMerge(firstRowIndex = 5, lastRowIndex = 6, firstColumnIndex = 1, lastColumnIndex = 2)
2.11. 自定义拦截器
2.11.1. 下拉选择框
2.11.1.1. 拦截器
public class CustomSheetWriteHandler implements SheetWriteHandler {
@Override
public void afterSheetCreate(SheetWriteHandlerContext context) {
// 区间设置 第一列第一行和第二行的数据。由于第一行是头,所以第一、二行的数据实际上是第二三行
CellRangeAddressList cellRangeAddressList = new CellRangeAddressList(1, 2, 0, 0);
DataValidationHelper helper = context.getWriteSheetHolder().getSheet().getDataValidationHelper();
DataValidationConstraint constraint = helper.createExplicitListConstraint(new String[] {"测试1", "测试2"});
DataValidation dataValidation = helper.createValidation(constraint, cellRangeAddressList);
context.getWriteSheetHolder().getSheet().addValidationData(dataValidation);
}
}
2.11.1.2. 导出代码
public void exportPullDown(HttpServletResponse response) throws IOException {
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
//encode防止中文乱码,与easyexcel无关
String fileName = URLEncoder.encode("图片导出测试","UTF-8").replaceAll("\\+", "%20");
response.addHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
//防止获取不到文件名称
response.addHeader("Access-Control-Expose-Headers", "Content-disposition");
EasyExcel.write(response.getOutputStream(),User.class)
.sheet()
.registerWriteHandler(new CustomSheetWriteHandler())
.doWrite(users);
}