基于Java POI實現(xiàn)動態(tài)列Excel導出的通用方法
更新時間:2025年07月14日 08:42:23 作者:自由的瘋
在企業(yè)級開發(fā)中,Excel導出功能是常見需求,當面對前端動態(tài)傳參、列數不確定的場景時,編寫通用的動態(tài)列導出方法能顯著提升開發(fā)效率,本文將結合Java POI框架,詳細解析如何實現(xiàn)支持多級表頭、動態(tài)列求和及合并單元格的Excel導出功能,并提供完整代碼示例與使用說明
一、核心功能特性
1. 動態(tài)列處理
- 支持從前端接收?
?List<String>???類型的列名集合(??cellList???),結合固定列數組(??strCloumnAry??)動態(tài)拼接最終列集合 - 使用?
?LinkedHashMap??維護列順序,確保導出列與傳入順序一致
2. 多級表頭支持
- 通過?
?headerNum??參數控制表頭層級(1-3 級) - 表頭名稱通過?
?||???分隔(如??"船舶信息||完船日期||噸位"??),自動解析為多級結構
3. 數據統(tǒng)計功能
- 自動識別數值型列(?
?Number???類型),生成??totalMap??存儲列求和結果 - 支持在導出數據末尾添加 "合計" 行,并合并單元格顯示
4. 樣式與布局優(yōu)化
- 統(tǒng)一設置單元格邊框、居中對齊、字體大小
- 自動調整列寬適應內容
- 多級表頭行合并相同標題單元格,提升可讀性
二、關鍵代碼解析
1. 列集合初始化
LinkedHashMap<String, Integer> allColumn = new LinkedHashMap<>();
// 先添加固定列
for (int i = 0; i < strCloumnAry.length; i++) {
allColumn.putIfAbsent(strCloumnAry[i], i);
}
// 再添加動態(tài)列(避免重復)
int i = strCloumnAry.length;
for (String key : cellList) {
if (!allColumn.containsKey(key)) {
allColumn.put(key, i++);
}
}
- 使用?
?LinkedHashMap??保持順序,固定列在前,動態(tài)列在后 - 通過?
?putIfAbsent??避免重復列名導致的索引沖突
2. 多級表頭生成
if (headerNum == 2) { // 二級表頭處理
for (String key : allColumn.keySet()) {
String[] parts = key.split("\|\|"); // 按||拆分
if (parts.length == 2) {
// 一級表頭行
Cell cell1 = headerRow1.createCell(allColumn.get(key));
cell1.setCellValue(parts[0]);
// 二級表頭行
Cell cell2 = headerRow2.createCell(allColumn.get(key));
cell2.setCellValue(parts[1]);
}
}
}
- 通過?
?split("\|\|")??解析多級表頭名稱 - 根據?
?headerNum??創(chuàng)建對應行數的表頭行(1-3 級) - 同一列的多級表頭單元格共享相同列索引
3. 數據行與合計行
// 寫入數據行
int row = headerNum; // 表頭行下方開始寫數據
for (Map<String, Object> data : datas) {
Row dataRow = sheet.createRow(row++);
for (Map.Entry<String, Integer> entry : allColumn.entrySet()) {
Cell cell = dataRow.createCell(entry.getValue());
cell.setCellValue(data.get(entry.getKey()) != null ? data.get(entry.getKey()).toString() : "");
}
}
// 寫入合計行
Row totalRow = sheet.createRow(row);
totalRow.createCell(0).setCellValue("合計");
for (Map.Entry<String, Object> entry : totalMap.entrySet()) {
int colIndex = allColumn.get(entry.getKey());
Cell cell = totalRow.createCell(colIndex);
cell.setCellValue(entry.getValue() != null ? entry.getValue().toString() : "");
}
// 合并合計行標題單元格
sheet.addMergedRegion(new CellRangeAddress(row, row, 0, maxSp));
- ?
?totalMap??通過遍歷數據行自動計算數值列總和 - 合計行標題 "合計" 通過?
?CellRangeAddress??合并多個列單元格 - ?
?maxSp??變量動態(tài)計算需要合并的列范圍
4. 單元格樣式設置
// 創(chuàng)建通用樣式 CellStyle cellStyle = workbook.createCellStyle(); cellStyle.setAlignment(HorizontalAlignment.CENTER); cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); cellStyle.setBorderTop(BorderStyle.THIN); cellStyle.setBorderBottom(BorderStyle.THIN); cellStyle.setBorderLeft(BorderStyle.THIN); cellStyle.setBorderRight(BorderStyle.THIN); // 表頭字體設置 Font headerFont = workbook.createFont(); headerFont.setFontHeightInPoints((short) 10); cellStyle.setFont(headerFont);
- 統(tǒng)一設置水平 / 垂直居中對齊
- 添加細邊框樣式
- 表頭使用 10 號字體
三、使用示例
1. 方法參數說明
| 參數名 | 類型 | 說明 |
|---|---|---|
| response | HttpServletResponse | Servlet 響應對象,用于輸出文件流 |
| datas | List<Map<String,Object>> | 導出數據集合,每個 Map 代表一行數據 |
| cellList | List | 動態(tài)列名集合(如前端勾選的列) |
| baseFileName | String | 基礎文件名(不含時間戳) |
| strAry | String[] | 固定列顯示名稱數組(與 strCloumnAry 對應) |
| strCloumnAry | String[] | 固定列字段名數組(如數據庫字段名) |
| headerNum | int | 表頭層級(1-3 級) |
2. 調用示例
// 假設前端傳入動態(tài)列名為["price","quantity"]
List<String> cellList = Arrays.asList("price", "quantity");
// 固定列字段名與顯示名
String[] strCloumnAry = {"name", "date"};
String[] strAry = {"商品名稱", "日期"};
// 構造模擬數據
List<Map<String, Object>> datas = new ArrayList<>();
Map<String, Object> data1 = new HashMap<>();
data1.put("name", "蘋果");
data1.put("date", "2023-10-01");
data1.put("price", 5.99);
data1.put("quantity", 100);
datas.add(data1);
// 調用導出方法(二級表頭示例)
exportDynamicExcel(response, datas, cellList, "商品銷售報表", strAry, strCloumnAry, 2);
3. 表頭命名規(guī)范
多級表頭通過??||??分隔,如:
- 一級表頭:?
?"銷售額"?? - 二級表頭:?
?"季度數據||銷售額"?? - 三級表頭:?
?"年度匯總||季度數據||銷售額"??
四、優(yōu)化與擴展建議
1. 類型適配優(yōu)化
當前代碼僅處理??Number??類型數值求和,可擴展支持:
- ?
?String??類型數值轉換(需校驗格式) - ?
?LocalDate???/??LocalDateTime??類型日期格式化顯示
2. 樣式擴展
- 添加條件格式(如數值超過閾值時標紅)
- 支持不同背景色區(qū)分奇偶行
- 表頭行添加自動篩選功能
3. 性能優(yōu)化
- 大數據量場景可改用?
?SXSSFWorkbook??(基于磁盤緩存的流式處理) - 合并單元格操作可批量處理,減少?
?sheet.addMergedRegion??調用次數
4. 錯誤處理增強
- 添加參數校驗(如?
?cellList???與??strCloumnAry??重復校驗) - 提供更友好的異常提示信息(如字段名不存在)
五、總結
本文提供的動態(tài)列 Excel 導出方法通過靈活的參數設計,實現(xiàn)了:
- 動態(tài)列與固定列的混合展示
- 1-3 級多級表頭的自動解析
- 數值列自動求和與合計行生成
- 統(tǒng)一的單元格樣式與布局優(yōu)化
適用于需要根據用戶選擇動態(tài)展示列的管理系統(tǒng)(如數據報表、權限控制場景)。實際使用中可根據業(yè)務需求進一步擴展類型適配、樣式定制等功能,提升導出文件的實用性與美觀性。
以上就是基于Java POI實現(xiàn)動態(tài)列Excel導出的通用方法的詳細內容,更多關于Java POI動態(tài)列Excel導出的資料請關注腳本之家其它相關文章!
相關文章
java遠程連接Linux執(zhí)行命令的3種方式完整代碼
在一些Java應用程序中需要執(zhí)行一些Linux系統(tǒng)命令,例如服務器資源查看、文件操作等,這篇文章主要給大家介紹了關于java遠程連接Linux執(zhí)行命令的3種方式,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2024-06-06
解決SpringBoot項目中l(wèi)og4j與logback的Jar包沖突問題
這篇文章主要給大家介紹了解決SpringBoot項目中l(wèi)og4j與logback的Jar包沖突問題,文中有詳細的解決方法和沖突的原因,有遇到相同問題的朋友可以參考閱讀本文2023-10-10

