在我們平時工作中經常會遇到要操作Excel的功能,比如導出個用戶信息或者訂單信息的Excel報表。你肯定聽說過POI這個東西,可以實現。但是POI實現的API確實很麻煩,它需要寫那種逐行解析的代碼(類似Xml解析)。今天給大家推薦一款非常好用的Excel導入導出工具EasyPoi,希望對大家有所幫助!
EasyPoi簡介
用慣了SpringBoot的朋友估計會想到,有沒有什么辦法可以直接定義好需要導出的數據對象,然后添加幾個注解,直接自動實現Excel導入導出功能?
EasyPoi正是這么一款工具,如果你不太熟悉POI,想簡單地實現Excel操作,用它就對了!
EasyPoi的目標不是替代POI,而是讓一個不懂導入導出的人也能快速使用POI完成Excel的各種操作,而不是看很多API才可以完成這樣的工作。
集成
在SpringBoot中集成EasyPoi非常簡單,只需添加如下一個依賴即可,真正的開箱即用!
<dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-spring-boot-starter</artifactId> <version>4.4.0</version> </dependency>
使用
接下來介紹下EasyPoi的使用,以會員信息和訂單信息的導入導出為例,分別實現下簡單的單表導出和具有關聯信息的復雜導出。
簡單導出
我們以會員信息列表導出為例,使用EasyPoi來實現下導出功能,看看是不是夠簡單!
- 首先創建一個會員對象
Member
,封裝會員信息;
/** * 購物會員 * Created by macro on 2021/10/12. */ @Data @EqualsAndHashCode(callSuper = false) public class Member { @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 = "手機號", 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
注解,可以將對象信息直接導出到Excel中去,下面對注解中的屬性做個介紹; - name:Excel中的列名;
- width:指定列的寬度;
- needMerge:是否需要縱向合並單元格;
- format:當屬性為時間類型時,設置時間的導出導出格式;
- desensitizationRule:數據脫敏處理,
3_4
表示只顯示字符串的前3
位和后4
位,其他為*
號; - replace:對屬性進行替換;
- suffix:對數據添加后綴。
- 接下來我們在Controller中添加一個接口,用於導出會員列表到Excel,具體代碼如下;
/** * EasyPoi導入導出測試Controller * Created by macro on 2021/10/12. */ @Controller @Api(tags = "EasyPoiController", description = "EasyPoi導入導出測試") @RequestMapping("/easyPoi") public class EasyPoiController { @ApiOperation(value = "導出會員列表Excel") @RequestMapping(value = "/exportMemberList", method = RequestMethod.GET) public void exportMemberList(ModelMap map, HttpServletRequest request, HttpServletResponse response) { List<Member> memberList = LocalJsonUtil.getListFromJson("json/members.json", Member.class); 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數據並轉化為對象,例如此處使用的members.json
;
- 運行項目,直接通過Swagger訪問接口,注意在Swagger中訪問接口無法直接下載,需要點擊返回結果中的下載按鈕才行,訪問地址:http://localhost:8088/swagger-ui/
-
- 下載完成后,查看下文件,一個標准的Excel文件已經被導出了。
簡單導入
導入功能實現起來也非常簡單,下面以會員信息列表的導入為例。
- 在Controller中添加會員信息導入的接口,這里需要注意的是使用
@RequestPart
注解修飾文件上傳參數,否則在Swagger中就沒法顯示上傳按鈕了; -
/** * EasyPoi導入導出測試Controller * Created by macro on 2021/10/12. */ @Controller @Api(tags = "EasyPoiController", description = "EasyPoi導入導出測試") @RequestMapping("/easyPoi") public class EasyPoiController { @ApiOperation("從Excel導入會員列表") @RequestMapping(value = "/importMemberList", method = RequestMethod.POST) @ResponseBody public CommonResult importMemberList(@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("導入失敗!"); } } }
然后在Swagger中測試接口,選擇之前導出的Excel文件即可,導入成功后會返回解析到的數據。
復雜導出
當然EasyPoi也可以實現更加復雜的Excel操作,比如導出一個嵌套了會員信息和商品信息的訂單列表,下面我們來實現下!
- 首先添加商品對象
Product
,用於封裝商品信息; -
/** * 商品 * Created by macro on 2021/10/12. */ @Data @EqualsAndHashCode(callSuper = false) public class Product { @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 = "商品副標題", width = 30) private String subTitle; @Excel(name = "品牌名稱", width = 20) private String brandName; @Excel(name = "商品價格", width = 10) private BigDecimal price; @Excel(name = "購買數量", width = 10, suffix = "件") private Integer count; }
然后添加訂單對象
Order
,訂單和會員是一對一關系,使用@ExcelEntity
注解表示,訂單和商品是一對多關系,使用@ExcelCollection
注解表示,Order
就是我們需要導出的嵌套訂單數據; -
/** * 訂單 * Created by macro on 2021/10/12. */ @Data @EqualsAndHashCode(callSuper = false) public class Order { @Excel(name = "ID", width = 10,needMerge = true) private Long id; @Excel(name = "訂單號", width = 20,needMerge = true) private String orderSn; @Excel(name = "創建時間", 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中添加導出訂單列表的接口,由於有些會員信息我們不需要導出,可以調用
ExportParams
中的setExclusions
方法排除掉; -
/** * EasyPoi導入導出測試Controller * Created by macro on 2021/10/12. */ @Controller @Api(tags = "EasyPoiController", description = "EasyPoi導入導出測試") @RequestMapping("/easyPoi") public class EasyPoiController { @ApiOperation(value = "導出訂單列表Excel") @RequestMapping(value = "/exportOrderList", method = RequestMethod.GET) public void exportOrderList(ModelMap map, HttpServletRequest request, HttpServletResponse response) { List<Order> orderList = getOrderList(); ExportParams params = new ExportParams("訂單列表", "訂單列表", ExcelType.XSSF); //導出時排除一些字段 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中訪問接口測試,導出訂單列表對應Excel;
下載完成后,查看下文件,EasyPoi導出復雜的Excel也是很簡單的!
自定義處理
如果你想對導出字段進行一些自定義處理,EasyPoi也是支持的,比如在會員信息中,如果用戶沒有設置昵稱,我們添加下
暫未設置
信息。- 我們需要添加一個處理器繼承默認的
ExcelDataHandlerDefaultImpl
類,然后在exportHandler
方法中實現自定義處理邏輯; -
/** * 自定義字段處理 * Created by macro on 2021/10/13. */ public class MemberExcelDataHandler extends ExcelDataHandlerDefaultImpl<Member> { @Override public Object exportHandler(Member obj, String name, Object value) { if("昵稱".equals(name)){ String emptyValue = "暫未設置"; 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 public Object importHandler(Member obj, String name, Object value) { return super.importHandler(obj, name, value); } }
然后修改Controller中的接口,調用
MemberExcelDataHandler
處理器的setNeedHandlerFields
設置需要自定義處理的字段,並調用ExportParams
的setDataHandler
設置自定義處理器; -
/** * EasyPoi導入導出測試Controller * Created by macro on 2021/10/12. */ @Controller @Api(tags = "EasyPoiController", description = "EasyPoi導入導出測試") @RequestMapping("/easyPoi") public class EasyPoiController { @ApiOperation(value = "導出會員列表Excel") @RequestMapping(value = "/exportMemberList", method = RequestMethod.GET) public void exportMemberList(ModelMap map, HttpServletRequest request, HttpServletResponse response) { List<Member> memberList = LocalJsonUtil.getListFromJson("json/members.json", Member.class); ExportParams params = new ExportParams("會員列表", "會員列表", ExcelType.XSSF); //對導出結果進行自定義處理 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); } }
- 再次調用導出接口,我們可以發現昵稱已經添加默認設置了。
-
總結
體驗了一波EasyPoi,它使用注解來操作Excel的方式確實非常好用。如果你想生成更為復雜的Excel的話,可以考慮下它的模板功能。
參考資料
項目官網:https://gitee.com/lemur/easypoi
項目源碼地址
https://github.com/macrozheng/mall-learning/tree/master/mall-tiny-easypoi
- 再次調用導出接口,我們可以發現昵稱已經添加默認設置了。
- 我們需要添加一個處理器繼承默認的