想實現(xiàn)Excel報表的導(dǎo)入導(dǎo)出,首先想到的就是POI蝶锋,POI的API確實麻煩,需要我們逐行解析什往。
EasyPoi一款非常好用的Excel導(dǎo)入導(dǎo)出工具扳缕。
EasyPoi正是這么一款工具,如果你不太熟悉POI别威,想簡單地實現(xiàn)Excel操作躯舔,用它就對了!
EasyPoi的目標(biāo)不是替代POI省古,而是讓一個不懂導(dǎo)入導(dǎo)出的人也能快速使用POI完成Excel的各種操作粥庄,而不是看很多API才可以完成這樣的工作。
在SpringBoot中集成EasyPoi非常簡單衫樊,只需添加如下一個依賴即可飒赃,真正的開箱即用!
1.添加依賴
<dependency>
? ? <group>cn.afterturn</group>
? ? <artifactId>easypoi-spring-boot-starter</artifactId>
? ? <version>4.4.0</version>
</dependency>
2.使用場景
以會員信息和訂單信息的導(dǎo)入導(dǎo)出為例科侈,分別實現(xiàn)下簡單的單表導(dǎo)出和具有關(guān)聯(lián)信息的復(fù)雜導(dǎo)出载佳。
3.簡單導(dǎo)出
以會員信息列表導(dǎo)出為例,使用EasyPoi來實現(xiàn)下導(dǎo)出功能臀栈,看看是不是夠簡單蔫慧!
首先創(chuàng)建一個會員對象Member,封裝會員信息权薯;
@Data
@EqualsAndHashCode(callSuper?=?false)
public?classMember{
????@Excel(name?=?"ID",?width?=?10)
????private?Long?id;
????@Excel(name?=?"用戶名",?width?=?20,?needMerge?=?true)
????private?String?username;
????private?String?password;
????@Excel(name?=?"昵稱",?width?=?20,?needMerge?=?true)
????private?String?nickname;
????@Excel(name?=?"出生日期",?width?=?20,?format?=?"yyyy-MM-dd")
????private?Date?birthday;
????@Excel(name?=?"手機(jī)號",?width?=?20,?needMerge?=?true,?desensitizationRule?=?"3_4")
????private?String?phone;
????private?String?icon;
????@Excel(name?=?"性別",?width?=?10,?replace?=?{"男_0",?"女_1"})
????private?Integer?gender;
}
在此我們就可以看到EasyPoi的核心注解@Excel姑躲,通過在對象上添加@Excel注解睡扬,可以將對象信息直接導(dǎo)出到Excel中去,下面對注解中的屬性做個介紹黍析;
name:Excel中的列名卖怜;
width:指定列的寬度;
needMerge:是否需要縱向合并單元格阐枣;
format:當(dāng)屬性為時間類型時马靠,設(shè)置時間的導(dǎo)出導(dǎo)出格式;
desensitizationRule:數(shù)據(jù)脫敏處理蔼两,3_4表示只顯示字符串的前3位和后4位甩鳄,其他為*號;
replace:對屬性進(jìn)行替換额划;
suffix:對數(shù)據(jù)添加后綴妙啃。
接下來我們在Controller中添加一個接口,用于導(dǎo)出會員列表到Excel俊戳,具體代碼如下揖赴;
@Controller
@Api(tags?=?"EasyPoiController",?description?=?"EasyPoi導(dǎo)入導(dǎo)出測試")
@RequestMapping("/easyPoi")
public?classEasyPoiController{
? @ApiOperation(value?=?"導(dǎo)出會員列表Excel")
? @RequestMapping(value?=?"/exportMemberList",?method?=?RequestMethod.GET)
? ?publicvoidexportMemberList(ModelMap?map,HttpServletRequest?request,HttpServletResponse?res????????ponse){
? ? ? ?List<Member>?memberList?=?LocalJsonUtil.getListFromJson("json/members.json",?Member.clas);
? ? ? ?ExportParams?params?=?new?ExportParams("會員列表",?"會員列表",?ExcelType.XSSF);
? ? ? ?map.put(NormalExcelConstants.DATA_LIST,?memberList);
? ? ? ?map.put(NormalExcelConstants.CLASS,?Member.class);
? ? ? ?map.put(NormalExcelConstants.PARAMS,?params);
? ? ? ?map.put(NormalExcelConstants.FILE_NAME,?"memberList");
? ? ? ?PoiBaseView.render(map,?request,?response,?NormalExcelConstants.EASYPOI_EXCEL_VIEW);
????}
}
LocalJsonUtil工具類,可以直接從resources目錄下獲取JSON數(shù)據(jù)并轉(zhuǎn)化為對象品抽,例如此處使用的members.json储笑;
運行項目甜熔,直接通過Swagger訪問接口圆恤,注意在Swagger中訪問接口無法直接下載,需要點擊返回結(jié)果中的下載按鈕才行腔稀,訪問地址:http://localhost:8088/swagger-ui/
下載完成后盆昙,查看下文件,一個標(biāo)準(zhǔn)的Excel文件已經(jīng)被導(dǎo)出了焊虏。
4.簡單導(dǎo)入
在Controller中添加會員信息導(dǎo)入的接口淡喜,這里需要注意的是使用@RequestPart注解修飾文件上傳參數(shù),否則在Swagger中就沒法顯示上傳按鈕了诵闭;
@Controller
@Api(tags?=?"EasyPoiController",?description?=?"EasyPoi導(dǎo)入導(dǎo)出測試")
@RequestMapping("/easyPoi")
public?classEasyPoiController{
????@ApiOperation("從Excel導(dǎo)入會員列表")
????@RequestMapping(value?=?"/importMemberList",?method?=?RequestMethod.POST)
????@ResponseBody
????publicCommonResultimportMemberList(@RequestPart("file")MultipartFile?file){
????????ImportParams?params?=?new?ImportParams();
????????params.setTitleRows(1);
????????params.setHeadRows(1);
????????try?{
????????????List<Member>?list?=?ExcelImportUtil.importExcel(
????????????????????file.getInputStream(),
????????????????????Member.class,params);
????????????return?CommonResult.success(list);
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?CommonResult.failed("導(dǎo)入失斄锻拧!");
????????}
????}
}
然后在Swagger中測試接口疏尿,選擇之前導(dǎo)出的Excel文件即可瘟芝,導(dǎo)入成功后會返回解析到的數(shù)據(jù)。
5.復(fù)雜導(dǎo)出
當(dāng)然EasyPoi也可以實現(xiàn)更加復(fù)雜的Excel操作褥琐,比如導(dǎo)出一個嵌套了會員信息和商品信息的訂單列表锌俱,下面我們來實現(xiàn)下!
首先添加商品對象Product敌呈,用于封裝商品信息贸宏;
@Data
@EqualsAndHashCode(callSuper?=?false)
public?classProduct{
????@Excel(name?=?"ID",?width?=?10)
????private?Long?id;
????@Excel(name?=?"商品SN",?width?=?20)
????private?String?productSn;
????@Excel(name?=?"商品名稱",?width?=?20)
????private?String?name;
????@Excel(name?=?"商品副標(biāo)題",?width?=?30)
????private?String?subTitle;
????@Excel(name?=?"品牌名稱",?width?=?20)
????private?String?brandName;
????@Excel(name?=?"商品價格",?width?=?10)
????private?BigDecimal?price;
????@Excel(name?=?"購買數(shù)量",?width?=?10,?suffix?=?"件")
????private?Integer?count;
}
然后添加訂單對象Order造寝,訂單和會員是一對一關(guān)系,使用@ExcelEntity注解表示吭练,訂單和商品是一對多關(guān)系诫龙,使用@ExcelCollection注解表示,Order就是我們需要導(dǎo)出的嵌套訂單數(shù)據(jù)鲫咽;
@Data
@EqualsAndHashCode(callSuper?=?false)
public?classOrder{
????@Excel(name?=?"ID",?width?=?10,needMerge?=?true)
????private?Long?id;
????@Excel(name?=?"訂單號",?width?=?20,needMerge?=?true)
????private?String?orderSn;
????@Excel(name?=?"創(chuàng)建時間",?width?=?20,?format?=?"yyyy-MM-dd?HH:mm:ss",needMerge?=?true)
????private?Date?createTime;
????@Excel(name?=?"收貨地址",?width?=?20,needMerge?=?true?)
????private?String?receiverAddress;
????@ExcelEntity(name?=?"會員信息")
????private?Member?member;
????@ExcelCollection(name?=?"商品列表")
????private?List<Product>?productList;
}
接下來在Controller中添加導(dǎo)出訂單列表的接口赐稽,由于有些會員信息我們不需要導(dǎo)出,可以調(diào)用ExportParams中的setExclusions方法排除掉浑侥;
@Controller
@Api(tags?=?"EasyPoiController",?description?=?"EasyPoi導(dǎo)入導(dǎo)出測試")
@RequestMapping("/easyPoi")
public?classEasyPoiController{
@ApiOperation(value?=?"導(dǎo)出訂單列表Excel")
@RequestMapping(value?=?"/exportOrderList",?method?=?RequestMethod.GET)
publicvoidexportOrderList(ModelMap?map,HttpServletRequest?request,HttpServletResponse?response){
? ? ? List<Order>?orderList?=?getOrderList();
? ? ? ExportParams?params?=?new?ExportParams("訂單列表",?"訂單列表",?ExcelType.XSSF);
? ? ? //導(dǎo)出時排除一些字段
? ? ? params.setExclusions(new?String[]{"ID",?"出生日期",?"性別"});
? ? ? map.put(NormalExcelConstants.DATA_LIST,?orderList);
? ? ? map.put(NormalExcelConstants.CLASS,?Order.class);
? ? ? map.put(NormalExcelConstants.PARAMS,?params);
? ? ? map.put(NormalExcelConstants.FILE_NAME,?"orderList");
? ? ? PoiBaseView.render(map,?request,?response,?NormalExcelConstants.EASYPOI_EXCEL_VIEW);
????}
}
在Swagger中訪問接口測試姊舵,導(dǎo)出訂單列表對應(yīng)Excel;
6.自定義處理
如果你想對導(dǎo)出字段進(jìn)行一些自定義處理寓落,EasyPoi也是支持的括丁,比如在會員信息中,如果用戶沒有設(shè)置昵稱伶选,我們添加下暫未設(shè)置信息史飞。
我們需要添加一個處理器繼承默認(rèn)的ExcelDataHandlerDefaultImpl類,然后在exportHandler方法中實現(xiàn)自定義處理邏輯仰税;
public?classMemberExcelDataHandlerextendsExcelDataHandlerDefaultImpl{
??@Override
??publicObjectexportHandler(Member?obj,?String?name,?Object?value){
????if("昵稱".equals(name)){
??????String?emptyValue?=?"暫未設(shè)置";
??????if(value==null){
????????return?super.exportHandler(obj,name,emptyValue);
??????}
??????if(value?instanceof?String&&StrUtil.isBlank((String)?value)){
????????return?super.exportHandler(obj,name,emptyValue);
??????}
????}
????return?super.exportHandler(obj,?name,?value);
??}
??@Override
??publicObjectimportHandler(Member?obj,?String?name,?Object?value){
????return?super.importHandler(obj,?name,?value);
??}
}
然后修改Controller中的接口构资,調(diào)用MemberExcelDataHandler處理器的setNeedHandlerFields設(shè)置需要自定義處理的字段,并調(diào)用ExportParams的setDataHandler設(shè)置自定義處理器陨簇;
@Controller
@Api(tags?=?"EasyPoiController",?description?=?"EasyPoi導(dǎo)入導(dǎo)出測試")
@RequestMapping("/easyPoi")
public?classEasyPoiController{
????@ApiOperation(value?=?"導(dǎo)出會員列表Excel")
????@RequestMapping(value?=?"/exportMemberList",?method?=?RequestMethod.GET)
????publicvoidexportMemberList(ModelMap?map,
HttpServletRequest?request,
HttpServletResponse?response){
? ? ? ?List<Member>?memberList?=?LocalJsonUtil.getListFromJson("json/members.json",?Member.class);
? ExportParams?params?=?new?ExportParams("會員列表",?"會員列表",?ExcelType.XSSF);
? ?//對導(dǎo)出結(jié)果進(jìn)行自定義處理
? ?MemberExcelDataHandler?handler?=?new?MemberExcelDataHandler();
? ? handler.setNeedHandlerFields(new?String[]{"昵稱"});
? ? ?params.setDataHandler(handler);
? ? ?map.put(NormalExcelConstants.DATA_LIST,?memberList);
? ? ?map.put(NormalExcelConstants.CLASS,?Member.class);
? ? ?map.put(NormalExcelConstants.PARAMS,?params);
? ? ?map.put(NormalExcelConstants.FILE_NAME,?"memberList");
? ? ? PoiBaseView.render(map,?request,?response,?NormalExcelConstants.EASYPOI_EXCEL_VIEW);
????}
}
再次調(diào)用導(dǎo)出接口吐绵,我們可以發(fā)現(xiàn)昵稱已經(jīng)添加默認(rèn)設(shè)置了。
體驗了一波EasyPoi河绽,它使用注解來操作Excel的方式確實非常好用己单。如果你想生成更為復(fù)雜的Excel的話,可以考慮下它的模板功能耙饰。
參考資料:
項目官網(wǎng):https://gitee.com/lemur/easypoi