使用EasyPoi完成復雜一對多excel表格導出功能全過程
業(yè)務需求
從一個簡單的倉庫業(yè)務說起,倉庫業(yè)務,會有進庫記錄,會有出庫記錄,會有庫存,客戶的需求就是需要一個庫存盤點單,盤點單通俗來講:將庫存中每個商品的出入庫記錄都統(tǒng)計出來,看看每個商品出過多少貨物,入過多少貨物,本月庫存多少,上月庫存多少。
需求難點
一個貨物會出過多次貨物,入過多次貨物,導出的 excel 就要做成 一對多 格式的導出
簡單舉例:
啤酒:入庫2次,出庫3次,最終體現(xiàn)在 excel 中效果如下圖:
通過 EasyPoi 實現(xiàn)需求
EasyPoi 文檔地址:http://doc.wupaas.com/docs/easypoi/easypoi-1c0u4mo8p4ro8
SpringBoot 使用:
<dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-base</artifactId> <version>4.2.0</version> </dependency> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-annotation</artifactId> <version>4.2.0</version> </dependency> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-web</artifactId> <version>4.2.0</version> </dependency>
Gradle 使用:
implementation 'cn.afterturn:easypoi-base:4.2.0' implementation 'cn.afterturn:easypoi-annotation:4.2.0' implementation 'cn.afterturn:easypoi-web:4.2.0'
使用 EasyPoi 提供的注解,自定義導出類模板
import cn.afterturn.easypoi.excel.annotation.Excel; import cn.afterturn.easypoi.excel.annotation.ExcelCollection; import cn.afterturn.easypoi.excel.annotation.ExcelIgnore; import lombok.Getter; import lombok.Setter; import java.io.Serializable; import java.math.BigDecimal; import java.util.Date; import java.util.List; /** * 導出 excel 模板類 */ @Getter @Setter public class ExportTemplate implements Serializable { @Excel(name = "序號", needMerge = true, type = 10) private int index; @Excel(name = "商品名稱", needMerge = true, width = 30.0) private String goodName; @Excel(name = "商品單位", needMerge = true) private String goodUnit; @Excel(name = "上月庫存數(shù)量", needMerge = true, type = 10) private Integer lastMonthSurplusNum; @Excel(name = "本月庫存數(shù)量", needMerge = true, type = 10) private Integer thisMonthSurplusNum; @ExcelCollection(name = "本月入庫信息") private List<GoodInItem> goodInItems; @ExcelCollection(name = "本月出庫信息") private List<GoodOutItem> goodOutItems; @Excel(name = "備注", needMerge = true, width = 30.0) private String remark; /** * 入庫信息 */ @Getter @Setter public static class GoodInItem { @Excel(name = "入庫日期", exportFormat = "yyyy-MM-dd", width = 20.50) private Date purchaseDate; @Excel(name = "入庫號", width = 25.50) private String purchaseNum; @Excel(name = "入庫單價", type = 10) private BigDecimal unitPrice; @Excel(name = "入庫數(shù)量", type = 10) private Integer totalNum; } /** * 出庫信息 */ @Getter @Setter public static class GoodOutItem { @Excel(name = "出庫日期", exportFormat = "yyyy-MM-dd", width = 20.50) private Date outDate; @Excel(name = "出庫號", width = 25.50) private String sellNum; @Excel(name = "出庫數(shù)量", type = 10) private Integer totalNum; @Excel(name = "成本金額", type = 10) private BigDecimal priceIn; @Excel(name = "銷售金額", type = 10) private BigDecimal priceOut; } }
實體類中使用的注解作用解釋:
- 1.@Getter lombok 注解,用于給所有屬性提供 getter 方法
- 2.@Setter lombok 注解,用于給所有屬性提供 setter 方法
- 3.@Excel easypoi 注解,name 就等于導出 excel 的列名稱,width 就是寬度,type 就是這個屬性的類型,1表示文本,默認也是文本,10就是數(shù)字,needMerge 表示是否縱向合并單元格,也就是上下列合并
- 4.@ExcelCollection easypoi 注解,name 就等于導出 excel 的列名稱,被此注解標注的集合,就等于在其列下面創(chuàng)建對等數(shù)量的行,就類似于這種
最后模板弄好之后,就可以通過easypoi 的工具類來導出,easypoi 推薦的導出工具類如下:
這個方法的三個參數(shù)表示含義解釋:
ExportParams
:參數(shù)表示Excel 導出參數(shù)設置類,easypoi 自定義的類pojoClass
:你要導出的類模板dataSet
:數(shù)據(jù)集合
具體實現(xiàn)
@GetMapping(value = "export") public void export(HttpServletRequest req, HttpServletResponse resp) { List<ExportTemplate> exportData = new ArrayList(); // 步驟1:構(gòu)建要導出excel的數(shù)據(jù)集合 for (int i = 0; i < 5; i++) { ExportTemplate data = new ExportTemplate(); data.setIndex(i); data.setGoodName("測試商品"); data.setGoodUnit("瓶"); data.setLastMonthSurplusNum(5); // 上月庫存 data.setThisMonthSurplusNum(3); // 本月庫存 // ... 剩下的就是類似的加值 exportData.add(data); } try { // 步驟2:開始導出 excel ExportParams params = new ExportParams(); params.setTitle("庫存盤點單標題"); params.setSheetName("庫存盤點單工作表名稱"); params.setType(ExcelType.XSSF); Workbook workbook = ExcelExportUtil.exportExcel(params, ExportTemplate.class, exportData); String nowStr = DateTimeFormatter.ofPattern(LocalDateTime.now()).format("yyyyMMddHHmm"); // 時間串 String fileName = nowStr + "_庫存盤點單"; // 文件名稱 String tempDir = "C:/Users/huxim/Downloads"; File filePath = new File(tempDir + File.separator); if (!filePath.exists()) filePath.mkdirs(); // 如果文件目錄不存在就創(chuàng)建這個目錄 FileOutputStream fos = new FileOutputStream(tempDir + File.separator + fileName); workbook.write(fos); fos.close(); resp.setContentType("application/octet-stream"); resp.setCharacterEncoding("utf-8"); response.addHeader("Content-disposition", "attachment; filename=" + this.makeDownloadFileName(req, fileName)); IOUtils.copy(new FileInputStream(tempFile), response.getOutputStream()); System.out.println("導出成功~~~"); } catch (Exception e) { throw new RuntimeException("導出 excel 失敗~~~"); } } /** * 判斷是否是 IE 瀏覽器 * 返回對應的字符串格式 */ public static String makeDownloadFileName(HttpServletRequest request, String fileName) { String agent = request.getHeader("User-Agent"); byte[] bytes = fileName.getBytes(StandardCharsets.UTF_8); if (agent.contains("MSIE") || agent.contains("Trident") || agent.contains("Edge")) { // IE return new String(bytes, StandardCharsets.UTF_8); } else { return new String(bytes, StandardCharsets.ISO_8859_1); } }
導出成功后的excel 就類似于如下這種:
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Spring @Profile注解實現(xiàn)多環(huán)境配置
這篇文章主要介紹了Spring @Profile注解實現(xiàn)多環(huán)境配置,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-04-04mybatisPlus如何使用MetaObjectHandler對字段進行更新
這篇文章主要介紹了mybatisPlus如何使用MetaObjectHandler對字段進行更新問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-04-04java數(shù)據(jù)結(jié)構(gòu)之樹基本概念解析及代碼示例
這篇文章主要介紹了java數(shù)據(jù)結(jié)構(gòu)之樹基本概念解析及代碼示例,介紹了樹的定義,基本術語,主要操作及實現(xiàn)等相關內(nèi)容,具有一定參考價值,需要的朋友可了解下。2017-11-11SpringBoot整合JWT框架,解決Token跨域驗證問題
Json web token (JWT), 是為了在網(wǎng)絡應用環(huán)境間傳遞聲明而執(zhí)行的一種基于JSON的開放標準((RFC 7519).定義了一種簡潔的,自包含的方法用于通信雙方之間以JSON對象的形式安全的傳遞信息。2021-06-06@Accessors(chain = true)注解報錯的解決方案
這篇文章主要介紹了@Accessors(chain = true)注解報錯的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06