「这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战」
通过学习 EasyExcel导入导出的简单实现 ,对EasyExcel使用有了初步的认识,这一次就来学习Web项目中使用EasyExcel实现导入导出以及自定义策略导出。
1. Excel上传导入服务
1.1 服务接口定义
基于Web的上传服务与本地读取Excel使用方式是一致的,而服务接口的定义则是基于文件上传的类型。
//excel上传服务接口
@RequestMapping("/uploadExcel")
public String uploadExcel(MultipartFile file){
try {
EasyExcel.read(file.getInputStream(), UserModel.class, new UserModelListener()).sheet().doRead();
return "success";
} catch (IOException e) {
e.printStackTrace();
return "fail";
}
}
定义上传服务时需要注意的有:
- 定义的接口参数应该为
MultipartFile对象,表示服务接受文件参数 - 使用
EasyExcel读取文件时,应该使用文件的字节流内容作为参数读取 - 导入实体模型类定义的属性要和Excel文件的列对应一致,默认顺序按照属性定义顺序
- 需要创建回调监听器时用于读取数据时回调处理
1.2 回调监听器定义
定义回调监听器时需要注意监听器是不能交给容器管理的,因此在监听器中调用Java Bean类时不能使用自动注入的方式,而需要使用构造器传递Bean。
//回调监听器中处理数据,不支持被容器管理
public class UserModelListener implements ReadListener<UserModel> {
private static final Logger log = LoggerFactory.getLogger(UserModelListener.class);
private UserService userService;
public UserModelListener(){
this.userService = new UserServiceImpl();
}
public UserModelListener(UserService userService){
this.userService = userService;
}
@Override
public void invoke(UserModel userModel, AnalysisContext analysisContext) {
log.info("解析到一条数据:{}", userModel.toString());
//指定其他操作
userService.select();
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
log.info("所有数据解析完成!");
//指定其他操作
}
}
2. Excel导出下载服务
基于Web服务的Excel导出功能与本地的区别就在于需要接口响应文件并由浏览器完成下载。
@RequestMapping("/downloadExcel")
public void downloadExcel(HttpServletResponse response) throws IOException {
//导出数据整理
List<UserModel> list = new ArrayList<>();
UserModel userModel = new UserModel();
userModel.setId("1");
userModel.setCode("123");
userModel.setName("tom");
list.add(userModel);
//设置相应数据类型
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
//URL编码防止中文乱码
String name = URLEncoder.encode("用户数据", "UTF-8");
//设置浏览器下载文件而不是渲染解析
response.setHeader("Content-Disposition","attachment;fileName=" + name + ".xlsx");
//数据写入Excel并响应
EasyExcel.write(response.getOutputStream(), UserModel.class).autoCloseStream(Boolean.FALSE).sheet("Sheet1").doWrite(list);
//可以用此方式输出json文件,包含内容转为json字符串
//response.getWriter().println(JSON.toJSONString(list));
}
定义Excel下载服务接口时需要注意:
- 下载文件服务不需要返回值,但是需要
HttpServletResponse参数设置返回内容 - response.setContentType()方法设置返回数据的类型,此处是excel文件
- 定义中文名称时使用
URLEncoder.encode()可以避免名称中文乱码 response.setHeader()方法设置Content-Disposition属性,告知浏览器下载文件而不是解析- 在
EasyExcel.write()方法中指定模型类,用来指定导出数据的数据列表头信息 - 使用
EasyExcel.autoCloseStream()设置写入数据到Excel时数据流不关闭
3. 自定义操作
截止目前,已经可以使用EasyExcel实现简单的Excel导入和导出服务了,对于复杂数据格式的导入导出则需要使用注解或者定义策略来完成。
3.1 注解实现自定义数据格式
在模型类上使用注解
@ColumnWidth(value = 25),设置导出数据列宽为25@HeadFontStyle(fontName = "等线",fontHeightInPoints = 11, bold = BooleanEnum.FALSE),设置导出数据表头字体格式,字体为等线、11号字、加粗@HeadStyle,标题样式@HeadRowHeight,标题行高
模型类属性字段上使用注解
@ExcelIgnore,忽略当前字段,数据导入导出时均会忽略该字段@ExcelProperty(value = "编号", order = 0),自定义字段在excel文件中样式- value中定义名称,表示数据列表头名称,可使用
value = {"用户信息","编号"}对多列分组处理 - order定义该字段在文件中显示顺序,从0开始,由小至大
- 导入时,如果没有指定
@ExcelProperty内容,则默认按照属性顺序对应文件列顺序 - 如果指定order,则按照order定义顺序排列属性与Excel数据列对应
- 如果指定value,则按照Excel列标题匹配导入
- value中定义名称,表示数据列表头名称,可使用
@DateTimeFormat(value = "yyyy-MM-dd"),自定义时间字段导出格式@ContentStyle,设置单元格内容格式@ContentFontStyle,设置单元格内容字体样式
3.2 自定义样式策略实现
对于导出数据的格式自定义方法,除了使用注解外,还可以使用定义策略实现。
EasyExcel导出Excel时还提供了registerWriteHandler()方法来设置导出文件数据格式策略。
//导出时绑定样式策略
EasyExcel.write("用户数据.xlsx", UserModel.class)
.sheet("Sheet1")
.registerWriteHandler(getCellStyleStrategy())
.doWrite(list);
自定义样式策略时,需要最终返回一个HorizontalCellStyleStrategy策略对象,该对象中可以指定数据标题的样式策略和内容的策略。
- WriteCellStyle,数据写入策略,可以用来定义标题或者内容的样式
- WriteFont,数据字体策略,设置数据中字体的样式、大小等属性
//定义策略类
private HorizontalCellStyleStrategy getCellStyleStrategy(){
//标题头的样式策略,设置表头样式
WriteCellStyle headWriteCellStyle = new WriteCellStyle();
//内容的策略,设置数据内容样式
WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
//字体策略
WriteFont writeFont = new WriteFont();
writeFont.setFontHeightInPoints((short)20);
contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
contentWriteCellStyle.setWriteFont(writeFont);
//总策略绑定头部和内容策略
HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle,contentWriteCellStyle);
return horizontalCellStyleStrategy;
}