EasyExcel--導入和導出Excel的方法

原文網址:EasyExcel--導入和導出Excel的方法_IT利刃出鞘的博客-CSDN博客

簡介

本文介紹SpringBoot整合EasyExcel導入和導出Excel的方法。

使用

Excel導入

實體類

@Data
public class OrderImportBO {@ExcelProperty("訂單號")@NotBlank(message = "訂單號不能為空")private String scOrderPoolId;@ExcelProperty("金額")private String amount;
}

Controller

@PostMapping("importOrder")
public void importOrder(@RequestPart MultipartFile file) {List<OrderImportBO> orderImportBOList = ExcelUtil.importExcel(file, OrderImportBO.class);
}

Excel導出

?實體類

@Data
public class OrderExportBO {@ExcelProperty("訂單號")@NotBlank(message = "訂單號不能為空")private String scOrderPoolId;@ExcelProperty("金額")private String amount;
}

Service

List<OrderExportVO> exportVOS = new ArrayList();
ExcelUtil.exportExcel(exportVOS, OrderExportVO.class);

詳細代碼

依賴

EasyExcel

<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.2.11</version>
</dependency>

整個pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.0.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.knife</groupId><artifactId>demo_EasyExcel_SpringBoot</artifactId><version>0.0.1-SNAPSHOT</version><name>demo_EasyExcel_SpringBoot</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.2.11</version></dependency><dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId><version>3.0.3</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.24</version><scope>provided</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>2.3.0.RELEASE</version></plugin></plugins></build></project>

Excel配置

字符串轉換器

package com.knife.excel.handler;import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty;public class StringConverter implements Converter<String> {@Overridepublic Class supportJavaTypeKey() {return String.class;}@Overridepublic CellDataTypeEnum supportExcelTypeKey() {return CellDataTypeEnum.STRING;}/*** 將excel對象轉成Java對象,這里讀的時候會調用*/@Overridepublic String convertToJavaData(CellData cellData, 
ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {return cellData.getStringValue().trim();}/*** 將Java對象轉成String對象,寫出的時候調用*/@Overridepublic CellData convertToExcelData(String value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {return new CellData(value);}
}

writeHandler

package com.knife.excel.halper;import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;import java.util.HashMap;
import java.util.List;
import java.util.Map;public class ExcelHandler extends AbstractColumnWidthStyleStrategy {private static final int MAX_COLUMN_WIDTH = 255;//因為在自動列寬的過程中,有些設置地方讓列寬顯得緊湊,所以做出了個判斷private static final int COLUMN_WIDTH = 20;private  Map<Integer, Map<Integer, Integer>> CACHE = new HashMap(8);public ExcelHandler() {}@Overrideprotected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {boolean needSetWidth = isHead || !CollectionUtils.isEmpty(cellDataList);if (needSetWidth) {Map<Integer, Integer> maxColumnWidthMap = (Map)CACHE.get(writeSheetHolder.getSheetNo());if (maxColumnWidthMap == null) {maxColumnWidthMap = new HashMap(16);CACHE.put(writeSheetHolder.getSheetNo(), maxColumnWidthMap);}Integer columnWidth = this.dataLength(cellDataList, cell, isHead);if (columnWidth >= 0) {if (columnWidth > MAX_COLUMN_WIDTH) {columnWidth = MAX_COLUMN_WIDTH;}else {if(columnWidth<COLUMN_WIDTH){columnWidth =columnWidth*2;}}Integer maxColumnWidth = (Integer)((Map)maxColumnWidthMap).get(cell.getColumnIndex());if (maxColumnWidth == null || columnWidth > maxColumnWidth) {((Map)maxColumnWidthMap).put(cell.getColumnIndex(), columnWidth);writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(),  columnWidth* 256);}}}}private  Integer dataLength(List<CellData> cellDataList, Cell cell, Boolean isHead) {if (isHead) {return cell.getStringCellValue().getBytes().length;} else {CellData cellData = (CellData)cellDataList.get(0);CellDataTypeEnum type = cellData.getType();if (type == null) {return -1;} else {switch(type) {case STRING:return cellData.getStringValue().getBytes().length;case BOOLEAN:return cellData.getBooleanValue().toString().getBytes().length;case NUMBER:return cellData.getNumberValue().toString().getBytes().length;default:return -1;}}}}public static HorizontalCellStyleStrategy getStyleStrategy(){// 頭的策略WriteCellStyle headWriteCellStyle = new WriteCellStyle();// 背景設置為灰色headWriteCellStyle.setFillForegroundColor(IndexedColors.ROYAL_BLUE.getIndex());WriteFont headWriteFont = new WriteFont();headWriteFont.setFontHeightInPoints((short)11);// 字體樣式headWriteFont.setFontName("Arial Unicode MS");headWriteFont.setColor(IndexedColors.WHITE.getIndex());headWriteCellStyle.setWriteFont(headWriteFont);//自動換行headWriteCellStyle.setWrapped(false);// 水平對齊方式headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);// 垂直對齊方式headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);// 內容的策略WriteCellStyle contentWriteCellStyle = new WriteCellStyle();// 這里需要指定 FillPatternType 為FillPatternType.SOLID_FOREGROUND 不然無法顯示背景顏色.頭默認了 FillPatternType所以可以不指定// contentWriteCellStyle.setFillPatternType(FillPatternType.SQUARES);// 背景白色contentWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());WriteFont contentWriteFont = new WriteFont();// 字體大小contentWriteFont.setFontHeightInPoints((short)11);// 字體樣式contentWriteFont.setFontName("宋體");contentWriteCellStyle.setWriteFont(contentWriteFont);//是否換行contentWriteCellStyle.setWrapped(false);//  垂直對齊方式contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);// 這個策略是 頭是頭的樣式 內容是內容的樣式 其他的策略可以自己實現return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);}
}

數據校驗

package com.bondex.oms.excel;import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.knife.util.BeanHelper;
import com.knife.util.ValidateUtil;public class ExcelValidateListener<T> extends AnalysisEventListener<T> {@Overridepublic void invoke(T bo, AnalysisContext analysisContext) {// 如果是空行,不處理if (BeanHelper.allFieldAreNull(bo)) {return;}int row = analysisContext.readRowHolder().getRowIndex() + 1;try {// 校驗輸入字段ValidateUtil.validate(bo);} catch (Exception e) {throw new RuntimeException("第[" + row + "]行數據校驗失敗:" + e.getMessage());}}@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {}
}

?Bean工具

package com.knife.util;import org.springframework.beans.BeanUtils;
import org.springframework.cglib.core.ReflectUtils;
import org.springframework.util.CollectionUtils;import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;public class BeanHelper {public static <T> List<T> convert(List<?> sources, Class<T> target) {if (CollectionUtils.isEmpty(sources)) {return new ArrayList<>();}List<T> targets = new LinkedList<>();for (Object source : sources) {T t = null;try {t = target.newInstance();} catch (Exception e) {throw new RuntimeException(e);}BeanUtils.copyProperties(source, t);targets.add(t);}return targets;}public static <T> T convert(Object source, Class<T> target) {if (source == null) {return null;}T t;try {t = target.newInstance();} catch (Exception e) {throw new RuntimeException(e);}BeanUtils.copyProperties(source, t);return t;}public static boolean allFieldAreNull(Object o) {Class<?> aClass = o.getClass();PropertyDescriptor[] beanProperties = ReflectUtils.getBeanProperties(aClass);for (PropertyDescriptor beanProperty : beanProperties) {Method readMethod = beanProperty.getReadMethod();try {Object value = readMethod.invoke(o);if (value != null) {return false;}} catch (IllegalAccessException | InvocationTargetException e) {throw new RuntimeException(e);}}return true;}
}

Excel工具類

package com.bondex.oms.util;import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.knife.entity.UserDTO;
import com.knife.util.UserDtoUtils;
import com.knife.excel.helper.ExcelHandler;
import com.knife.excel.helper.ExcelValidateListener;
import com.knife.excel.helper.HeadRowListener;
import com.knife.excel.helper.StringConverter;
import org.springframework.util.Assert;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;public class ExcelUtil {public static <T> void exportExcel(List<T> dataList,Class<T> tClass) {ServletRequestAttributes servletRequestAttributes =(ServletRequestAttributes)RequestContextHolder.getRequestAttributes();Assert.notNull(servletRequestAttributes, "RequestAttributes不能為null");HttpServletResponse response = servletRequestAttributes.getResponse();Assert.notNull(response, "Response不能為null");ServletOutputStream out = null;try {out = response.getOutputStream();} catch (IOException e) {throw new RuntimeException(e);}String fileName = "測試文件.xlsx";try {// 必須要轉一下,否則中文文件名會亂碼fileName = URLEncoder.encode(fileName, "UTF-8");} catch (UnsupportedEncodingException e) {throw new RuntimeException(e);}// 通知瀏覽器以附件的形式下載處理,設置返回頭要注意文件名有中文response.setHeader("Content-disposition", "attachment;filename=" + fileName);response.setContentType("multipart/form-data");response.setCharacterEncoding("utf-8");// 輸出流到瀏覽器下載EasyExcel.write(out).needHead(true).head(tClass).excelType(ExcelTypeEnum.XLSX).autoCloseStream(true).registerWriteHandler(new ExcelHandler()).registerWriteHandler(ExcelHandler.getStyleStrategy()).sheet(0, "Sheet1").doWrite(dataList);}public static <T> List<T> importExcel(MultipartFile file, Class<T> tClass) {return importExcel(file, tClass, 1, null);}public static <T> List<T> importExcel(MultipartFile file, Class<T> tClass, String sheet) {return importExcel(file, tClass, 1, sheet);}public static <T> List<T> importExcel(MultipartFile file,Class<T> tClass,Integer headRowNumber,String sheet) {InputStream inputStream;try {inputStream = file.getInputStream();} catch (IOException e) {throw new RuntimeException(e);}List<T> list = null;list = EasyExcel.read(inputStream).registerConverter(new StringConverter()).registerReadListener(new ExcelValidateListener<T>()).head(tClass)// 可以指定sheet名字,不指定或null則表示第1個.sheet(sheet).headRowNumber(headRowNumber).doReadSync();list.removeIf(BeanHelper::allFieldAreNull);return list;}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/72934.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/72934.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/72934.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

金融級安全加速:群聯SD-WAN如何兼顧防御與低延遲?

一、SD-WAN的核心價值 1. 傳統回源痛點 暴露風險&#xff1a;公網回源可能泄露源站IP&#xff0c;易遭針對性攻擊。延遲抖動&#xff1a;跨國業務因網絡擁堵導致延遲波動&#xff08;如金融交易超時&#xff09;。 2. 群聯方案優勢 加密專線&#xff1a;通過IPSec/SSL VPN建…

Apache Tomcat漏洞公開發布僅30小時后即遭利用

近日&#xff0c;Apache Tomcat曝出一項安全漏洞&#xff0c;在公開發布概念驗證&#xff08;PoC&#xff09;僅30小時后&#xff0c;該漏洞即遭到攻擊者利用。這一漏洞編號為CVE-2025-24813&#xff0c;主要影響以下版本&#xff1a; 1. Apache Tomcat 11.0.0-M1 至 11.0.2 …

計算機體系結構作業2

1 P108 有一條動態多功能流水線由5段組成(如圖3.35所示),加法用1、3、4、5段,乘法用1、2、5段,第2段的時間為2△t,其余各段的時間均為△t,而且流水線的輸出可以直接返回輸入端或暫存于相應的流水寄存器中。若在該流水線上計算 ∑ i 4 ( A i B i ) \sum_i^4(A_iB_i) ∑i4?(Ai…

python-leetcode 60.分割回文串

題目&#xff1a; 給定一個字符串S,請將S分割成一些子串&#xff0c;使每個子串都是回文串&#xff0c;返回S所有可能的分割方案 方法一&#xff1a;回溯深度優先搜索 1. 主要思想 使用 深度優先搜索&#xff08;DFS&#xff09; 遍歷 s 的所有可能劃分方式。使用 回溯&…

Java EE 進階:MyBatis

MyBatis是一個優秀的持久化框架&#xff0c;用于簡化JDBC的開發。 持久層就是持久化訪問的層&#xff0c;就是數據訪問層&#xff08;Dao&#xff09;&#xff0c;用于訪問數據庫的。 MyBatis使用的準備工作 創建項目&#xff0c;導入mybatis的啟動依賴&#xff0c;mysql的驅…

Go語言的基礎類型

一基礎數據類型 一、布爾型&#xff08;Bool&#xff09; 定義&#xff1a;表示邏輯真 / 假&#xff0c;僅有兩個值&#xff1a;true 和 false內存占用&#xff1a;1 字節使用場景&#xff1a;條件判斷、邏輯運算 二、數值型&#xff08;Numeric&#xff09; 1. 整數類型&…

【愚公系列】《高效使用DeepSeek》019-外語學習

??【技術大咖愚公搬代碼:全棧專家的成長之路,你關注的寶藏博主在這里!】?? ??開發者圈持續輸出高質量干貨的"愚公精神"踐行者——全網百萬開發者都在追更的頂級技術博主! ?? 江湖人稱"愚公搬代碼",用七年如一日的精神深耕技術領域,以"…

發布第四代液晶電視,TCL引領全新美學境界

在不斷革新的消費電子領域中&#xff0c;電視行業在視覺體驗上正面臨重要的美學挑戰。如何打破全面屏時代的物理束縛&#xff0c;將家居空間提升到“視覺無界”的層次&#xff0c;以及如何讓尖端技術更好地服務于影像沉浸感&#xff0c;成為行業關注的焦點。 3月10日&#xff…

劍指 Offer II 113. 課程順序

comments: true edit_url: https://github.com/doocs/leetcode/edit/main/lcof2/%E5%89%91%E6%8C%87%20Offer%20II%20113.%20%E8%AF%BE%E7%A8%8B%E9%A1%BA%E5%BA%8F/README.md 劍指 Offer II 113. 課程順序 題目描述 現在總共有 numCourses 門課需要選&#xff0c;記為 0 到 n…

【C++】STL庫面試常問點

STL庫 什么是STL庫 C標準模板庫&#xff08;Standard Template Libiary&#xff09;基于泛型編程&#xff08;模板&#xff09;&#xff0c;實現常見的數據結構和算法&#xff0c;提升代碼的復用性和效率。 STL庫有哪些組件 STL庫由以下組件構成&#xff1a; ● 容器&#xf…

【問題解決】Postman 測試報錯 406

現象 Tomcat 日志 org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.logException Resolved org.springframework.web.HttpMediaTypeNotAcceptableException: No acceptable representation HTTP狀態 406 - 不可接收 的報錯&#xff0c;核心原因 客…

第3節:AWK的特點和優勢

1 第3節&#xff1a;AWK的特點和優勢 AWK是一種功能強大的文本處理工具&#xff0c;具有以下特點和優勢&#xff1a; 1.1.1 簡潔性 AWK的語法簡潔明了&#xff0c;對于簡單的數據處理任務&#xff0c;通常只需編寫簡短的命令即可完成。例如&#xff0c;要從一個文本文件中提…

Flutter 打包 ipa出現錯誤問題 exportArchive

一、錯誤信息: Encountered error while creating the IPA: error: exportArchive: "Runner.app" requires a provisioning profile with the Push Notifications feature. Try distributing the app in Xcode: open /project/your_app/build/ios/archive/Runner.…

STC89C52單片機學習——第28節: [12-2] AT24C02數據存儲秒表(定時器掃描按鍵數碼管)

寫這個文章是用來學習的,記錄一下我的學習過程。希望我能一直堅持下去,我只是一個小白,只是想好好學習,我知道這會很難&#xff0c;但我還是想去做&#xff01; 本文寫于&#xff1a;2025.03.20 51單片機學習——第28節: [12-2] AT24C02數據存儲&秒表&#xff08;定時器掃…

Verilog-HDL/SystemVerilog/Bluespec SystemVerilog vscode 配置

下載 verible https://github.com/chipsalliance/verible的二進制包 然后配置 vscode

STM32使用HAL庫,模擬UART輸出字符串

測試芯片是STM32F103C8T6&#xff0c;直接封裝好了&#xff0c;波特率是 9600 MyDbg.h #ifndef __MYDBG_H #define __MYDBG_H #include "stm32f1xx_hal.h" #include <stdio.h> #include <stdarg.h>/*使用GPIO口 模擬 UART 輸出字符串 */ //初始化調試…

[工控機安全] 使用DriverView快速排查不可信第三方驅動(附詳細圖文教程)

導語&#xff1a; 在工業控制領域&#xff0c;設備驅動程序的安全性至關重要。第三方驅動可能存在兼容性問題、安全漏洞甚至惡意代碼&#xff0c;威脅設備穩定運行。本文將手把手教你使用 DriverView工具&#xff0c;高效完成工控機驅動安全檢查&#xff0c;精準識別可疑驅動&a…

HTML5響應式使用css媒體查詢

HTML 負責搭建頁面結構&#xff0c;CSS 負責樣式設計&#xff0c;并且通過媒體查詢實現了較好的響應式效果&#xff0c;能夠適應不同屏幕尺寸下面就是寫了一個詳細的實例。 CSS 部分 * {margin: 0;padding: 0;box-sizing: border-box; } * 是通配選擇器&#xff0c;會選中頁面…

洛谷P1434 [SHOI2002] 滑雪

P1434 [SHOI2002] 滑雪 - 洛谷 代碼區&#xff1a; #include<algorithm> #include<iostream> #include<cstring> using namespace std;const int MAX 105; int r, c; int arr[MAX][MAX], dp[MAX][MAX]; int xindex[4] {-1,1,0,0};//上下左右 int yindex[…

【操作系統】進程間通信方式

進程間通信方式 前言 / 概述一、管道管道命名管道 二、消息隊列三、共享內存四、信號量信號量概述互斥訪問條件同步信號 五、socket總結 前言 / 概述 每個進程的用戶地址空間都是獨立的&#xff0c;?般而言是不能互相訪問的&#xff0c;但內核空間是每個進程都共享的&#xff…