Java Hutool 包工具類推薦 ExcelUtil 包引入 hutool包版本號可根據實際情況更換 <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.4.M1</ ...
Java Hutool 包工具類推薦 ExcelUtil
包引入
hutool包版本號可根據實際情況更換
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.4.M1</version>
</dependency>
除hutool包之外,還需要引入操作Excel必要包
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-full</artifactId>
<version>5.0.0</version>
</dependency>
一般簡單表頭Excel封裝工具類
直接上代碼
package io.supers.common.utils;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import cn.hutool.poi.excel.style.StyleUtil;
import io.supers.framework.em.BaseErrorEnum;
import io.supers.framework.exception.RRException;
import org.apache.commons.collections.CollectionUtils;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* Excel 工具類
*
* @author guoc
* @date 2022年05月31日 下午 17:21
*/
public class ExcelUtils {
/**
* 下載 Excel 模板 (只有表頭的 Excel)
*
* @param response response
* @param headers 表頭
* @param fileName 文件名
*/
public static void exportHeaders(HttpServletResponse response, List<String> headers, String fileName) {
export(response, null, headers, fileName);
}
/**
* 導出或下載 Excel 公用方法
*
* @param response 當前請求的 HttpServletResponse
* @param rows 需要寫入的數據 List
* @param fileName 最終文件名
*/
public static void export(HttpServletResponse response, List<Map<String, Object>> rows, List<String> headers, String fileName) {
// 獲取 Writer
ExcelWriter writer = ExcelUtil.getWriter(true);
// 寫入表頭
writer = writer.writeHeadRow(headers);
// 若是有數據 則寫入數據
if (CollectionUtils.isNotEmpty(rows)) {
writer.write(rows);
}
Workbook workbook = writer.getWorkbook();
CellStyle defaultCellStyle = StyleUtil.createDefaultCellStyle(workbook);
DataFormat format = writer.getWorkbook().createDataFormat();
// 預設為 文本格式
defaultCellStyle.setDataFormat(format.getFormat("@"));
// 預設為 居中
defaultCellStyle.setAlignment(HorizontalAlignment.CENTER);
for (int i = 0; i < headers.size(); i++) {
String h = headers.get(i);
h = h == null ? " " : h;
writer.setColumnStyle(i, defaultCellStyle);
// 預設寬度為 3 * 表頭字元數
writer.setColumnWidth(i, 3 * h.length());
}
try {
// 彈出下載對話框的文件名,不能為中文,中文請自行編碼
fileName = URLUtil.encode(fileName);
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
response.setContentType(ExcelUtil.XLSX_CONTENT_TYPE);
// 輸出
ServletOutputStream out = response.getOutputStream();
writer.flush(out, true);
// 關閉writer,釋放記憶體
writer.close();
//此處記得關閉輸出Servlet流
IoUtil.close(out);
} catch (IOException e) {
e.printStackTrace();
throw new RRException(BaseErrorEnum.COMMON_ERROR, "下載文件失敗!\n" + e.getMessage());
}
}
/**
* 讀取上傳到後臺的excel
*
* @param file MultipartFile 上傳的文件
* @return 數據列表
* @throws IOException e
*/
public static List<Map<String, Object>> readExcelRows(MultipartFile file) throws IOException {
return ExcelUtil.getReader(file.getInputStream()).readAll();
}
}
工具類封裝了三個方法, 只寫入表頭方法, 寫入表頭和數據方法 和 讀取表格數據列表方法。
三個方法的操作簡單,看代碼就能明白,不多贅述了。
複雜表頭或表格內合併單元格寫入
合併單元格核心方法
// cn.hutool.poi.excel.ExcelWriter#merge(int, int, int, int, java.lang.Object, boolean)
/**
* 合併某行的單元格,並寫入對象到單元格<br>
* 如果寫到單元格中的內容非null,行號自動+1,否則當前行號不變<br>
* 樣式為預設標題樣式,可使用{@link #getHeadCellStyle()}方法調用後自定義預設樣式
*
* @param firstRow 起始行,0開始
* @param lastRow 結束行,0開始
* @param firstColumn 起始列,0開始
* @param lastColumn 結束列,0開始
* @param content 合併單元格後的內容
* @param isSetHeaderStyle 是否為合併後的單元格設置預設標題樣式,只提取邊框樣式
* @return this
* @since 4.0.10
*/
public ExcelWriter merge(int firstRow, int lastRow, int firstColumn, int lastColumn, Object content, boolean isSetHeaderStyle) {
Assert.isFalse(this.isClosed, "ExcelWriter has been closed!");
CellStyle style = null;
if (null != this.styleSet) {
style = styleSet.getStyleByValueType(content, isSetHeaderStyle);
}
return merge(firstRow, lastRow, firstColumn, lastColumn, content, style);
}
看完一般表頭寫入的代碼,可以得知,此工具類寫入表頭時只需傳入表頭的字元串列表,即 List<String>,若是遇到動態表頭時,則可以通過遍歷的操作,先生成出導出數據中所有需要的表頭信息,即可為下一步的寫入數據的數據列表List<Map<String,Object>> 做準備了。
若是遇到某列或某些列中有合併單元格的,一般都有規律的,可以遍曆數據時根據合併的數據項內容通過合併單元格方法進行合併單元格操作。
總結
通過以上方法,可以處理絕大多數情況的導出寫入和基本所有的導入讀取(導入時的模板儘量規定為簡單表頭)。
寫入寫出數據基本上都使用的是Map<String,Object>,若是要轉成JavaBean,自行寫方法對應即可。