本文主要介绍easypoi导出Excel的代码示例;自己之前手动实现过导出工具类《编码技巧——导出工具类》,基于实体和注解,通过反射来映射实体字段和exce列的关系;在部分工程里面看到了easypoi的二方包,于是准备试用下,记录下如何引入并使用Easypoi的过程;
总的来说,easypoi基于Apache poi二次封装的开源二方包,用起来也比较简单,也提供了注解方式导出,并且在顺序、层级、颜色宽度、单元格合并等样式处理上,提供了丰富的注解属性和接口,推荐使用;
easypoi是为了让开发者快速的实现excel、word、pdf的导入导出,基于Apache poi基础上的一个工具包;功能如下:
(1)基于注解的导入导出,可以灵活定义的表头字段,修改注解就可以修改Excel;
(2)支持常用的样式自定义;
(3)支持一对多的导出/导入;
(4)支持模板的导出,一些常见的标签,自定义标签;
(5)支持HTML/Excel转换;
(6)支持word、图片、excel的导出;
因为本篇介绍的是使用easypoi注解方式的示例,先介绍下常用的注解;
1. @ExcelTarget
@ExcelTarget注解作用于最外层的对象,可以这么理解——这个类与一个excel对应(类属性对应excel的列);在使用easypoi的API导出excel生成Workbook对象时,作为参数传入,如下:
/*** @description 导出实体类*/
@Data
@ExcelTarget("auditFlowExport")
public class AuditFlowExport {...
}// 调用easypoi的API生成excel对象
final Workbook sheets = ExcelExportUtil.exportExcel(exportParams, AuditFlowExport.class, exportList);
2. @Excel
@Excel 注解是作用到Filed上面,是对Excel一列的一个描述,这个注解是必须要的注解,使用示例如下:
/*** 一级审批人,excel列名:一级审批人、顺序6、宽度20、分组"审批人信息"*/@Excel(name = "一级审批人", orderNum = "6", width = 20, groupName = "审批人信息")private String firstAuditor;
3. @ExcelEntity
@ExcelEntity注解表示一个继续深入导出的实体,是作用一个类型为实体的属性上面;
4. @ExcelCollection
@ExcelCollection注解表示一个集合,主要针对一对多的导出,作用在类型是List的属性上面;比如一个工单对应多个审批人,审批人就可以用集合表示如下:
/*** 审核人信息*/@ExcelCollection(name = "审核人信息", orderNum = "6")private List stepAndAuditorList;
需求背景
将工单记录以Excel格式导出给审计人员,每条记录包括工单的基本信息;由于不同工单的审核层级不同,因此将审核人信息合并展示;
以下是接入及实现的步骤:
1. 引入依赖
当前工程为SpringBoot项目,引入以下依赖;
cn.afterturn easypoi-spring-boot-starter 4.0.0
需要注意的是由于easypoi的依赖内部依赖原生的poi,所以引入了easypoi的依赖之后,需要把原生的poi的依赖删掉,不然可能遇到类冲突;
2. 定义导出数据对应的类
通过注解方式定义字段的excel列名、宽度、字体等;因为里面存在一对多(List类型给的属性),因此其他字段的注解属性加了needMerge = true,表示合并单元格;
import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelCollection;
import cn.afterturn.easypoi.excel.annotation.ExcelTarget;
import lombok.Data;import java.util.Date;
import java.util.List;/*** @author Akira* @description 导出实体类*/
@Data
@ExcelTarget("auditFlowExport")
public class AuditFlowExport {/*** 工单id*/@Excel(name = "审批单号", orderNum = "1", needMerge = true)private Long flowId;/*** 工单标题*/@Excel(name = "流程名称", orderNum = "2", width = 50, needMerge = true)private String title;/*** 发起人*/@Excel(name = "发起人", orderNum = "3", width = 18, needMerge = true)private String submitorName;/*** 工单创建时间 格式yyyy-MM-dd HH:mm:ss*/@Excel(name = "发起时间", orderNum = "4", exportFormat = "yyyy-MM-dd HH:mm:ss", width = 25, needMerge = true)private Date createTime;/*** 业务模块编码*/@Excel(name = "归属项目", orderNum = "5", width = 25, needMerge = true)private String secondSubModuleCodeName;/*** 审核人信息 因为存在一对多,因此其他列属性定义needMerge = true 即合并单元格*/@ExcelCollection(name = "审核人信息", orderNum = "6")private List stepAndAuditorList;/*** 详情信息*/@Excel(name = "详情信息", orderNum = "7", width = 120, needMerge = true)private String displayText;@Datapublic static class StepAndAuditorExport {@Excel(name = "审核层级", orderNum = "1", width = 10)private int step;@Excel(name = "审核人", orderNum = "2", width = 18)private String auditor;}
}
3. 定义导出格式
调用导出方法时,其中一个参数就是样式;easypoi已经默认了一套样式,有自定义样式需求时,支持实现原默认样式类来扩展样式;下面的样式比较简单,仅将表头的字体设置大一号且加粗;
/*** @author Akira* @description 简单样式 仅统一字体*/
public class ExcelStyleUtil extends ExcelExportStylerDefaultImpl {public ExcelStyleUtil(Workbook workbook) {super(workbook);}/*** 列表头*/@Overridepublic CellStyle getTitleStyle(short color) {CellStyle cellStyle = super.getTitleStyle(color);// 仅将表头的字体设置大一号且加粗cellStyle.setFont(getFont(workbook, 11, true));cellStyle.setFillForegroundColor(HSSFColor.HSSFColorPredefined.LIGHT_TURQUOISE.getIndex());return cellStyle;}/*** 行样式*/@Overridepublic CellStyle stringSeptailStyle(Workbook workbook, boolean isWarp) {CellStyle cellStyle = super.stringSeptailStyle(workbook, isWarp);cellStyle.setFont(getFont(workbook, 10, false));return cellStyle;}/*** 这里设置表头的格式,最上面的一行*/@Overridepublic CellStyle getHeaderStyle(short color) {CellStyle cellStyle = super.getHeaderStyle(color);cellStyle.setFont(getFont(workbook, 10, true));return cellStyle;}/*** 这里设置循环行,没有样式的一行*/@Overridepublic CellStyle stringNoneStyle(Workbook workbook, boolean isWarp) {CellStyle cellStyle = super.stringNoneStyle(workbook, isWarp);cellStyle.setFont(getFont(workbook, 10, false));return cellStyle;}/*** 字体样式** @param size 字体大小* @param isBold 是否加粗* @return*/private Font getFont(Workbook workbook, int size, boolean isBold) {Font font = workbook.createFont();// 字体样式font.setFontName("微软雅黑");// 是否加粗font.setBold(isBold);// 字体大小font.setFontHeightInPoints((short) size);return font;}}
4. 导出方法
其核心就是调用easypoi封装好的ExcelExportUtil#exportExcel方法,返回Workbook对象,然后向response里面写字节流;
/*** 导出** @param response* @param pageQuery*/public void export(HttpServletResponse response, AuditFlowPageQuery query) {// 查询结果并转换成导出类型AuditFlowExportfinal List exportList = buildExportList(query);// 不需要标题栏和二级标题 这里仅定义sheet的名称final ExportParams exportParams = new ExportParams(null, null, "导出数据");// 设置导出样式exportParams.setStyle(ExcelStyleUtil.class);// easypoi的核心方法 将java的List写成excel的每一行数据final Workbook sheets = ExcelExportUtil.exportExcel(exportParams, AuditFlowExport.class, exportList);// 导出文件try {String fileName = new String("记录导出结果.xls".getBytes("GBK"), StandardCharsets.ISO_8859_1);response.setContentType("application/octet-stream");response.setHeader("Content-disposition", "attachment;filename=" + fileName);OutputStream outputStream = response.getOutputStream();response.flushBuffer();sheets.write(outputStream);// 写完数据关闭流outputStream.close();log.warn("export success. [pageQuery={} total={}] ", JSON.toJSONString(pageQuery), exportList.size());} catch (IOException e) {log.error("export error! [pageQuery={}] e:{}", JSON.toJSONString(pageQuery), e);}}}
5. 接口定义
一般的导出接口controller写法,默认GET方式,比较简单;
/*** 我的可读工单导出*/@RequestMapping(value = {"/audit/flow/export"})public DefaultResponseDTO export(AuditFlowPageQuery pageQuery, HttpServletResponse response) {try {userAuditFlowService.export(response, pageQuery);return DefaultResponseDTO.success(Boolean.TRUE);} catch (Exception e) {log.error("audit flow export error", e);return DefaultResponseDTO.fail(ResultCodeEnum.SERVER_BUSYNESS, "请稍后重试");}}
场景和代码都比较简单,如果想使用更加复杂的excel相关API的用法,可以参考下面的文章;
参考:
easypoi - gitee
使用easypoi导入导出Excel的操作手册
使用easypoi合并单元格(groupName)
easypoi导出一对多,合并单元格,且根据内容自适应行高
超级简单POI导出Excel实战
上一篇:R语言:转换—宽数据↔长数据
下一篇:汇编程序学习