精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

一款解決大文件內(nèi)存溢出的 Excel 處理工具

jf_ro2CN3Fa ? 來源:芋道源碼 ? 2023-07-03 16:11 ? 次閱讀

介紹

快速開始

引入依賴

簡單導(dǎo)出

定義實體類

復(fù)雜導(dǎo)出

簡單導(dǎo)入

參考資料

介紹

EasyExcel 是一個基于 Java 的、快速、簡潔、解決大文件內(nèi)存溢出的 Excel 處理工具。它能讓你在不用考慮性能、內(nèi)存的等因素的情況下,快速完成 Excel 的讀、寫等功能。

EasyExcel文檔地址:

https://easyexcel.opensource.alibaba.com/

基于 Spring Boot + MyBatis Plus + Vue & Element 實現(xiàn)的后臺管理系統(tǒng) + 用戶小程序,支持 RBAC 動態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能

項目地址:https://github.com/YunaiV/ruoyi-vue-pro

視頻教程:https://doc.iocoder.cn/video/

快速開始

引入依賴


com.alibaba
easyexcel
3.1.3

簡單導(dǎo)出

以導(dǎo)出用戶信息為例,接下來手把手教大家如何使用EasyExcel實現(xiàn)導(dǎo)出功能!

定義實體類

在EasyExcel中,以面向?qū)ο笏枷雭韺崿F(xiàn)導(dǎo)入導(dǎo)出,無論是導(dǎo)入數(shù)據(jù)還是導(dǎo)出數(shù)據(jù)都可以想象成具體某個對象的集合,所以為了實現(xiàn)導(dǎo)出用戶信息功能,首先創(chuàng)建一個用戶對象UserDO實體類,用于封裝用戶信息:

/**
*用戶信息
*
*@authorwilliam@StarImmortal
*/
@Data
publicclassUserDO{
@ExcelProperty("用戶編號")
@ColumnWidth(20)
privateLongid;

@ExcelProperty("用戶名")
@ColumnWidth(20)
privateStringusername;

@ExcelIgnore
privateStringpassword;

@ExcelProperty("昵稱")
@ColumnWidth(20)
privateStringnickname;

@ExcelProperty("生日")
@ColumnWidth(20)
@DateTimeFormat("yyyy-MM-dd")
privateDatebirthday;

@ExcelProperty("手機號")
@ColumnWidth(20)
privateStringphone;

@ExcelProperty("身高(米)")
@NumberFormat("#.##")
@ColumnWidth(20)
privateDoubleheight;

@ExcelProperty(value="性別",converter=GenderConverter.class)
@ColumnWidth(10)
privateIntegergender;
}

上面代碼中類屬性上使用了EasyExcel核心注解:

@ExcelProperty: 核心注解,value屬性可用來設(shè)置表頭名稱,converter屬性可以用來設(shè)置類型轉(zhuǎn)換器

@ColumnWidth: 用于設(shè)置表格列的寬度;

@DateTimeFormat: 用于設(shè)置日期轉(zhuǎn)換格式;

@NumberFormat: 用于設(shè)置數(shù)字轉(zhuǎn)換格式。

自定義轉(zhuǎn)換器

在EasyExcel中,如果想實現(xiàn)枚舉類型到字符串類型轉(zhuǎn)換(例如gender屬性:1 -> 男,2 -> 女),需實現(xiàn)Converter接口來自定義轉(zhuǎn)換器,下面為自定義GenderConverter性別轉(zhuǎn)換器代碼實現(xiàn):

/**
*Excel性別轉(zhuǎn)換器
*
*@authorwilliam@StarImmortal
*/
publicclassGenderConverterimplementsConverter{
@Override
publicClasssupportJavaTypeKey(){
returnInteger.class;
}

@Override
publicCellDataTypeEnumsupportExcelTypeKey(){
returnCellDataTypeEnum.STRING;
}

@Override
publicIntegerconvertToJavaData(ReadConverterContextcontext){
returnGenderEnum.convert(context.getReadCellData().getStringValue()).getValue();
}

@Override
publicWriteCellDataconvertToExcelData(WriteConverterContextcontext){
returnnewWriteCellData<>(GenderEnum.convert(context.getValue()).getDescription());
}
}
/**
*性別枚舉
*
*@authorwilliam@StarImmortal
*/
@Getter
@AllArgsConstructor
publicenumGenderEnum{

/**
*未知
*/
UNKNOWN(0,"未知"),

/**
*男性
*/
MALE(1,"男性"),

/**
*女性
*/
FEMALE(2,"女性");

privatefinalIntegervalue;

@JsonFormat
privatefinalStringdescription;

publicstaticGenderEnumconvert(Integervalue){
returnStream.of(values())
.filter(bean->bean.value.equals(value))
.findAny()
.orElse(UNKNOWN);
}

publicstaticGenderEnumconvert(Stringdescription){
returnStream.of(values())
.filter(bean->bean.description.equals(description))
.findAny()
.orElse(UNKNOWN);
}
}

定義接口

/**
*EasyExcel導(dǎo)入導(dǎo)出
*
*@authorwilliam@StarImmortal
*/
@RestController
@RequestMapping("/excel")
publicclassExcelController{

@GetMapping("/export/user")
publicvoidexportUserExcel(HttpServletResponseresponse){
try{
this.setExcelResponseProp(response,"用戶列表");
ListuserList=this.getUserList();
EasyExcel.write(response.getOutputStream())
.head(UserDO.class)
.excelType(ExcelTypeEnum.XLSX)
.sheet("用戶列表")
.doWrite(userList);
}catch(IOExceptione){
thrownewRuntimeException(e);
}
}

/**
*設(shè)置響應(yīng)結(jié)果
*
*@paramresponse響應(yīng)結(jié)果對象
*@paramrawFileName文件名
*@throwsUnsupportedEncodingException不支持編碼異常
*/
privatevoidsetExcelResponseProp(HttpServletResponseresponse,StringrawFileName)throwsUnsupportedEncodingException{
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
StringfileName=URLEncoder.encode(rawFileName,"UTF-8").replaceAll("+","%20");
response.setHeader("Content-disposition","attachment;filename*=utf-8''"+fileName+".xlsx");
}

/**
*讀取用戶列表數(shù)據(jù)
*
*@return用戶列表數(shù)據(jù)
*@throwsIOExceptionIO異常
*/
privateListgetUserList()throwsIOException{
ObjectMapperobjectMapper=newObjectMapper();
ClassPathResourceclassPathResource=newClassPathResource("mock/users.json");
InputStreaminputStream=classPathResource.getInputStream();
returnobjectMapper.readValue(inputStream,newTypeReference>(){
});
}
}

測試接口

運行項目,通過 Postman 或者 Apifox 工具來進行接口測試

注意:在 Apifox 中訪問接口后無法直接下載,需要點擊返回結(jié)果中的下載圖標才行,點擊之后方可對Excel文件進行保存。

接口地址:http://localhost:8080/excel/export/user

d9d6b51c-17b7-11ee-962d-dac502259ad0.pngda05fffc-17b7-11ee-962d-dac502259ad0.png

復(fù)雜導(dǎo)出

由于 EasyPoi 支持嵌套對象導(dǎo)出,直接使用內(nèi)置 @ExcelCollection 注解即可實現(xiàn),遺憾的是 EasyExcel 不支持一對多導(dǎo)出,只能自行實現(xiàn),通過此issues了解到,項目維護者建議通過自定義合并策略方式來實現(xiàn)一對多導(dǎo)出。

da25636a-17b7-11ee-962d-dac502259ad0.png

解決思路:只需把訂單主鍵相同的列中需要合并的列給合并了,就可以實現(xiàn)這種一對多嵌套信息的導(dǎo)出

自定義注解

創(chuàng)建一個自定義注解,用于標記哪些屬性需要合并單元格,哪個屬性是主鍵:

/**
*用于判斷是否需要合并以及合并的主鍵
*
*@authorwilliam@StarImmortal
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public@interfaceExcelMerge{
/**
*是否合并單元格
*
*@returntrue||false
*/
booleanmerge()defaulttrue;

/**
*是否為主鍵(即該字段相同的行合并)
*
*@returntrue||false
*/
booleanisPrimaryKey()defaultfalse;
}

定義實體類

在需要合并單元格的屬性上設(shè)置 @ExcelMerge 注解,二級表頭通過設(shè)置 @ExcelProperty 注解中 value 值為數(shù)組形式來實現(xiàn)該效果:

/**
*@authorwilliam@StarImmortal
*/
@Data
publicclassOrderBO{
@ExcelProperty(value="訂單主鍵")
@ColumnWidth(16)
@ExcelMerge(merge=true,isPrimaryKey=true)
privateStringid;

@ExcelProperty(value="訂單編號")
@ColumnWidth(20)
@ExcelMerge(merge=true)
privateStringorderId;

@ExcelProperty(value="收貨地址")
@ExcelMerge(merge=true)
@ColumnWidth(20)
privateStringaddress;

@ExcelProperty(value="創(chuàng)建時間")
@ColumnWidth(20)
@DateTimeFormat("yyyy-MM-ddHHss")
@ExcelMerge(merge=true)
privateDatecreateTime;

@ExcelProperty(value={"商品信息","商品編號"})
@ColumnWidth(20)
privateStringproductId;

@ExcelProperty(value={"商品信息","商品名稱"})
@ColumnWidth(20)
privateStringname;

@ExcelProperty(value={"商品信息","商品標題"})
@ColumnWidth(30)
privateStringsubtitle;

@ExcelProperty(value={"商品信息","品牌名稱"})
@ColumnWidth(20)
privateStringbrandName;

@ExcelProperty(value={"商品信息","商品價格"})
@ColumnWidth(20)
privateBigDecimalprice;

@ExcelProperty(value={"商品信息","商品數(shù)量"})
@ColumnWidth(20)
privateIntegercount;
}

數(shù)據(jù)映射與平鋪

導(dǎo)出之前,需要對數(shù)據(jù)進行處理,將訂單數(shù)據(jù)進行平鋪,orderList為平鋪前格式,exportData為平鋪后格式:

da5a96a2-17b7-11ee-962d-dac502259ad0.png

自定義單元格合并策略

當 Excel 中兩列主鍵相同時,合并被標記需要合并的列:

/**
*自定義單元格合并策略
*
*@authorwilliam@StarImmortal
*/
publicclassExcelMergeStrategyimplementsRowWriteHandler{

/**
*主鍵下標
*/
privateIntegerprimaryKeyIndex;

/**
*需要合并的列的下標集合
*/
privatefinalListmergeColumnIndexList=newArrayList<>();

/**
*數(shù)據(jù)類型
*/
privatefinalClasselementType;

publicExcelMergeStrategy(ClasselementType){
this.elementType=elementType;
}

@Override
publicvoidafterRowDispose(WriteSheetHolderwriteSheetHolder,WriteTableHolderwriteTableHolder,Rowrow,IntegerrelativeRowIndex,BooleanisHead){
//判斷是否為標題
if(isHead){
return;
}
//獲取當前工作表
Sheetsheet=writeSheetHolder.getSheet();
//初始化主鍵下標和需要合并字段的下標
if(primaryKeyIndex==null){
this.initPrimaryIndexAndMergeIndex(writeSheetHolder);
}
//判斷是否需要和上一行進行合并
//不能和標題合并,只能數(shù)據(jù)行之間合并
if(row.getRowNum()<=?1)?{
????????????return;
????????}
????????//?獲取上一行數(shù)據(jù)
????????Row?lastRow?=?sheet.getRow(row.getRowNum()?-?1);
????????//?將本行和上一行是同一類型的數(shù)據(jù)(通過主鍵字段進行判斷),則需要合并
????????if?(lastRow.getCell(primaryKeyIndex).getStringCellValue().equalsIgnoreCase(row.getCell(primaryKeyIndex).getStringCellValue()))?{
????????????for?(Integer?mergeIndex?:?mergeColumnIndexList)?{
????????????????CellRangeAddress?cellRangeAddress?=?new?CellRangeAddress(row.getRowNum()?-?1,?row.getRowNum(),?mergeIndex,?mergeIndex);
????????????????sheet.addMergedRegionUnsafe(cellRangeAddress);
????????????}
????????}
????}

????/**
?????*?初始化主鍵下標和需要合并字段的下標
?????*
?????*?@param?writeSheetHolder?WriteSheetHolder
?????*/
????private?void?initPrimaryIndexAndMergeIndex(WriteSheetHolder?writeSheetHolder)?{
????????//?獲取當前工作表
????????Sheet?sheet?=?writeSheetHolder.getSheet();
????????//?獲取標題行
????????Row?titleRow?=?sheet.getRow(0);
????????//?獲取所有屬性字段
????????Field[]?fields?=?this.elementType.getDeclaredFields();
????????//?遍歷所有字段
????????for?(Field?field?:?fields)?{
????????????//?獲取@ExcelProperty注解,用于獲取該字段對應(yīng)列的下標
????????????ExcelProperty?excelProperty?=?field.getAnnotation(ExcelProperty.class);
????????????//?判斷是否為空
????????????if?(null?==?excelProperty)?{
????????????????continue;
????????????}
????????????//?獲取自定義注解,用于合并單元格
????????????ExcelMerge?excelMerge?=?field.getAnnotation(ExcelMerge.class);
????????????//?判斷是否需要合并
????????????if?(null?==?excelMerge)?{
????????????????continue;
????????????}
????????????for?(int?i?=?0;?i?

定義接口

將自定義合并策略 ExcelMergeStrategy 通過 registerWriteHandler 注冊上去:

/**
*EasyExcel導(dǎo)入導(dǎo)出
*
*@authorwilliam@StarImmortal
*/
@RestController
@RequestMapping("/excel")
publicclassExcelController{

@GetMapping("/export/order")
publicvoidexportOrderExcel(HttpServletResponseresponse){
try{
this.setExcelResponseProp(response,"訂單列表");
ListorderList=this.getOrderList();
ListexportData=this.convert(orderList);
EasyExcel.write(response.getOutputStream())
.head(OrderBO.class)
.registerWriteHandler(newExcelMergeStrategy(OrderBO.class))
.excelType(ExcelTypeEnum.XLSX)
.sheet("訂單列表")
.doWrite(exportData);
}catch(IOExceptione){
thrownewRuntimeException(e);
}
}

/**
*設(shè)置響應(yīng)結(jié)果
*
*@paramresponse響應(yīng)結(jié)果對象
*@paramrawFileName文件名
*@throwsUnsupportedEncodingException不支持編碼異常
*/
privatevoidsetExcelResponseProp(HttpServletResponseresponse,StringrawFileName)throwsUnsupportedEncodingException{
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
StringfileName=URLEncoder.encode(rawFileName,"UTF-8").replaceAll("+","%20");
response.setHeader("Content-disposition","attachment;filename*=utf-8''"+fileName+".xlsx");
}
}

測試接口

運行項目,通過 Postman 或者 Apifox 工具來進行接口測試

注意:在 Apifox 中訪問接口后無法直接下載,需要點擊返回結(jié)果中的下載圖標才行,點擊之后方可對Excel文件進行保存。

接口地址:http://localhost:8080/excel/export/order

da8b135e-17b7-11ee-962d-dac502259ad0.pngdac00fe6-17b7-11ee-962d-dac502259ad0.png

簡單導(dǎo)入

以導(dǎo)入用戶信息為例,接下來手把手教大家如何使用EasyExcel實現(xiàn)導(dǎo)入功能!

/**
*EasyExcel導(dǎo)入導(dǎo)出
*
*@authorwilliam@StarImmortal
*/
@RestController
@RequestMapping("/excel")
@Api(tags="EasyExcel")
publicclassExcelController{

@PostMapping("/import/user")
publicResponseVOimportUserExcel(@RequestPart(value="file")MultipartFilefile){
try{
ListuserList=EasyExcel.read(file.getInputStream())
.head(UserDO.class)
.sheet()
.doReadSync();
returnResponseVO.success(userList);
}catch(IOExceptione){
returnResponseVO.error();
}
}
}
dafb5a4c-17b7-11ee-962d-dac502259ad0.png

責任編輯:彭菁

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 內(nèi)存
    +關(guān)注

    關(guān)注

    8

    文章

    2998

    瀏覽量

    73881
  • 文件
    +關(guān)注

    關(guān)注

    1

    文章

    561

    瀏覽量

    24695
  • Excel
    +關(guān)注

    關(guān)注

    4

    文章

    218

    瀏覽量

    55448

原文標題:SpringBoot 集成 EasyExcel 3.x 優(yōu)雅實現(xiàn) Excel 導(dǎo)入導(dǎo)出

文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    Linux平臺大文件生成和處理方法

    在日常工作中,為了驗證某些場景下的功能,經(jīng)常需要人為構(gòu)造大文件進行測試,有時需要用大文件來測試下載速度,有時需要用大文件來覆蓋磁盤空間;偶爾會看到
    發(fā)表于 07-14 16:38 ?3860次閱讀

    Python利用pandas讀寫Excel文件

    使用pandas模塊讀取Excel文件可以更為方便和快捷。pandas可以將Excel文件讀取為個DataFrame對象,方便進行數(shù)據(jù)
    的頭像 發(fā)表于 12-16 11:22 ?1273次閱讀
    Python利用pandas讀寫<b class='flag-5'>Excel</b><b class='flag-5'>文件</b>

    ReqMan需求提取和協(xié)同處理工具怎么樣看了就知道

    ReqMan是由德國engineering method AG公司開發(fā)的一款高效的、可自由定制的需求提取和協(xié)同處理工具。ReqMan 能夠?qū)DF、Word、Excel等格式的文檔提取出來并將需求條目化,同時提供了多種文檔格式之
    發(fā)表于 03-08 07:52

    介紹一款蘋果操作系統(tǒng)的電源管理工具

    Power Manager for Mac是蘋果操作系統(tǒng)上的一款筆記本電源管理工具,該工具支持蘋果系列的筆記本,可以有效地優(yōu)化蘋果系統(tǒng),結(jié)束不必要的系統(tǒng)任務(wù),同時還可以提高筆記本電池的使用量
    發(fā)表于 01-03 07:42

    基于PHP大文件上傳的研究和設(shè)計

    基于PHP大文件上傳的研究和設(shè)計,感興趣的可以看看。
    發(fā)表于 02-22 18:15 ?6次下載

    TXT大文件切割軟體應(yīng)用程序免費下載

    本文檔的主要內(nèi)容詳細是TXT大文件切割軟體應(yīng)用程序免費下載,可以切割任意大小的txt文件,可以根據(jù)大小,數(shù)量,標題等類別進行切割,絕對是大文件切割的必備工具,該軟體綠色免安裝,誰用誰知
    發(fā)表于 11-07 08:00 ?5次下載
    TXT<b class='flag-5'>大文件</b>切割軟體應(yīng)用程序免費下載

    內(nèi)存溢出內(nèi)存泄露的區(qū)別_內(nèi)存溢出的原因以及解決方法

    內(nèi)存溢出內(nèi)存泄露的區(qū)別是什么?內(nèi)存溢出怎么解決?內(nèi)存溢出
    發(fā)表于 06-01 10:27 ?2890次閱讀

    EXCEL大文件Vlookup工具”使用步驟資料下載

    電子發(fā)燒友網(wǎng)為你提供EXCEL大文件Vlookup工具”使用步驟資料下載的電子資料下載,更有其他相關(guān)的電路圖、源代碼、課件教程、中文資料、英文資料、參考設(shè)計、用戶指南、解決方案等資料,希望可以幫助到廣大的電子工程師們。
    發(fā)表于 04-28 08:55 ?16次下載
    <b class='flag-5'>EXCEL</b>“<b class='flag-5'>大文件</b>Vlookup<b class='flag-5'>工具</b>”使用步驟資料下載

    如何通過python輕松處理大文件

    眾所周知,python除了以簡潔著稱,其成熟的第三方庫功能也是很強大的,今天浩道帶大家看看如何通過python輕松處理大文件,真讓人直呼yyds 。
    的頭像 發(fā)表于 04-27 10:54 ?854次閱讀

    一款任務(wù)日程管理工具ToDoList

    ? 1.軟件介紹 2.軟件功能 3 試用感受 推薦給大家一款開源免費的任務(wù)日程管理工具ToDoList,是適合職場人尤其是程序員的經(jīng)典任務(wù)管理軟件,使用好的話會讓大家在工作中事半功倍。 1.軟件介紹
    的頭像 發(fā)表于 07-05 10:00 ?1256次閱讀
    <b class='flag-5'>一款</b>任務(wù)日程管<b class='flag-5'>理工具</b>ToDoList

    如何解決內(nèi)存溢出

    ,有時候會自動關(guān)閉軟件,重啟電腦或者軟件后釋放掉一部分內(nèi)存又可以正常運行該軟件,而由系統(tǒng)配置、數(shù)據(jù)流、用戶代碼等原因而導(dǎo)致的內(nèi)存溢出錯誤,即使用戶重新執(zhí)行任務(wù)依然無法避免 其實很簡單,在 Java 中,那就是 Out Of Me
    的頭像 發(fā)表于 09-25 10:54 ?1382次閱讀
    如何解決<b class='flag-5'>內(nèi)存</b><b class='flag-5'>溢出</b>

    java內(nèi)存溢出排查方法

    過程中常見的問題之,可能導(dǎo)致應(yīng)用程序崩潰、性能下降甚至系統(tǒng)崩潰。在本文中,將詳細介紹如何排查和解決Java內(nèi)存溢出問題。 、什么是Java內(nèi)存
    的頭像 發(fā)表于 11-23 14:46 ?3107次閱讀

    jvm內(nèi)存溢出故障排查

    JVM內(nèi)存溢出是常見且令人頭疼的問題,特別是在運行大型Java應(yīng)用程序或長時間運行的應(yīng)用程序時。當JVM分配給應(yīng)用程序的內(nèi)存不足以處理應(yīng)用程序所需的數(shù)據(jù)時,就會發(fā)生
    的頭像 發(fā)表于 12-05 11:04 ?778次閱讀

    jvm內(nèi)存溢出該如何定位解決

    超出限制和堆空間不足。 定位JVM內(nèi)存溢出問題是個比較復(fù)雜的任務(wù),需要結(jié)合工具和技術(shù)來進行分析和解決。本文將介紹些常用的調(diào)試和解決
    的頭像 發(fā)表于 12-05 11:05 ?1292次閱讀

    內(nèi)存溢出內(nèi)存泄漏:定義、區(qū)別與解決方案

    內(nèi)存溢出內(nèi)存泄漏:定義、區(qū)別與解決方案? 內(nèi)存溢出內(nèi)存泄漏是計算機科學中常見的問題,在開發(fā)和
    的頭像 發(fā)表于 12-19 14:10 ?2472次閱讀