最近公司有好几个需求都是关于导出统计报表到excel,并发送邮件到对应负责人,纠缠了一番之后,也对导出数据到excel有了一定经验,不至于每做一个导出功能就要写一大堆重复代码。以下是最近几天对easypoi的一些使用经验和心得。
首先是依赖的问题,我们需要添加以下三个easypoi的包,具体的作用也就见名思意了,不做解释。
cn.afterturn
easypoi-base
4.0.0
cn.afterturn
easypoi-web
4.0.0
cn.afterturn
easypoi-annotation
4.0.0
在使用之前先来介绍一下相关的easypoi注解:
其中上面我使用最多的就是@Excel,接下来就是详细介绍一下这个注解要如何使用,先来看到这个注解里面可以使用属性:
属性 | 类型 | 默认值 | 功能 |
---|---|---|---|
name | String | null | 列名,支持name_id |
needMerge | boolean | fasle | 是否需要纵向合并单元格(用于含有list中,单个的单元格,合并list创建的多个row) |
orderNum | String | "0" | 列的排序,支持name_id |
replace | String[] | {} | 值的替换 导出是{0男,1女} 导入反过来 |
savePath | String | "upload" | 导入文件保存路径 |
type | int | 1 | 导出类型: 1 是文本 2 是图片,3 是函数,10 是数字 默认是文本 |
width | double | 10 | 列宽 |
height | double | 10 | 列高,后期会统一使用@ExcelTarget的height |
isStatistics | boolean | fasle | 自动统计数据,再追加一行统计 |
isHyperlink | boolean | false | 超链接,如果是需要实现接口返回对象 |
isImportField | boolean | true | 校验字段,看看这个字段是不是导入的Excel中有,如果没有说明是错误的Excel,读取失败,支持name_id |
exportFormat | String | "" | 导出的时间格式,以这个是否为空来判断是否需要格式化日期 |
importFormat | String | "" | 导入的时间格式,以这个是否为空来判断是否需要格式化日期 |
format | String | "" | 时间格式,相当于同时设置了exportFormat 和 importFormat |
databaseFormat | String | "yyyyMMddHHmmss" | 导出时间设置,如果字段是Date类型则不需要设置 数据库如果是string 类型,这个需要设置这个数据库格式,用以转换时间格式输出 |
numFormat | String | "" | 数字格式化,参数是Pattern,使用的对象是DecimalFormat |
imageType | int | 1 | 导出类型 1 从file读取 2 是从数据库中读取 默认是文件 同样导入也是一样的 |
suffix | String | "" | 文字后缀,如"¥" 9 变成9¥ |
isWrap | boolean | true | 是否换行 即支持\n |
mergeRely | int[] | {} | 合并单元格依赖关系,比如第二列合并是基于第一列 则{0}就可以了 |
mergeVertical | boolean | fasle | 纵向合并内容相同的单元格 |
fixedIndex | int | -1 | 对应excel的列,忽略名字 |
isColumnHidden | boolean | false | 导出隐藏列 |
其余几个注解暂不做解释,先来进行实操,首先看到我们需要导出数据效果,如图:
然后我们看到对应的对象Bean,如下,这里需要注意第一列和第二列,首先needMerge和mergeVertical都是需要改为true,如果第二列需要在第一列的基础上进行合并就添加mergeRely={0},0就是第一列的意思。
import cn.afterturn.easypoi.excel.annotation.Excel;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
@Data
@Accessors(chain = true)
public class ExportProductShiftItemDetailDTO implements Serializable {
@Excel(name = "FBOX or SFT",width = 30, orderNum = "0",needMerge = true,mergeVertical = true)
private String productShitItemCode;
@Excel(name = "运输方式",width = 12, orderNum = "1",needMerge = true,mergeVertical = true, mergeRely = {0})
private String shipType;
@Excel(name = "分箱号",width = 20, orderNum = "2")
private String productShiftBoxCode;
@Excel(name = "SKU/POA",width = 12, orderNum = "3",height = 15.0D)
private String productCode;
@Excel(name = "三方条码",width = 20, orderNum = "4")
private String amazonCustomerLabel;
@Excel(name = "店铺",width = 15, orderNum = "5")
private String amazonShop;
@Excel(name = "每箱数量",width = 12, orderNum = "6")
private String quantity;
@Excel(name = "体积",width = 20, orderNum = "7")
private String volume;
@Excel(name = "重量",width = 12, orderNum = "8")
private String weight;
}
然后就是导出数据到excel部分,这里做一下封装,用起来就得心应手,看自己需要,先把数据组装成ExportParams
/**
*@title 表格的顶头标题
*@sheetName 表脚
*@dataList 数据源
*@tClass 数据源的bean模式
*/
public static Map getExcelSheetParam(String title, String sheetName, List dataList, Class tClass) throws SkbException {
Map excelParam = new HashMap<>();
ExportParams params = new ExportParams();
if(StringUtils.isNotBlank(title)){
params.setTitle(title);
}
params.setSheetName(sheetName);
params.setType(ExcelType.XSSF);
excelParam.put("title", params);
excelParam.put("entity", tClass);
excelParam.put("data", dataList);
return excelParam;
}
导出到workbook并输出到response
/**
*
* @param list 数据集
* @param excelType 文件类型ExcelType.HSSF/XSSF
* @return
* @throws SkbException
*/
public static void exportExcel(List
最后是调用部分
public void exportProductShiftBoxDetail(List productShiftItemIdList, HttpServletResponse response) throws SkbException {
List result = productShiftItemMapper.exportProductShiftBoxDetail(productShiftItemIdList);
if(org.apache.commons.collections.CollectionUtils.isNotEmpty(result)){
List
打完收工,你们也赶紧去试一下吧。