新聞中心
一、簡(jiǎn)介
在實(shí)際的業(yè)務(wù)系統(tǒng)開(kāi)發(fā)過(guò)程中,操作 Excel 實(shí)現(xiàn)數(shù)據(jù)的導(dǎo)入導(dǎo)出基本上是個(gè)非常常見(jiàn)的需求。

之前,我們有介紹一款非常好用的工具:EasyPoi,有讀者提出在數(shù)據(jù)量大的情況下,EasyPoi 會(huì)占用內(nèi)存大,性能不夠好,嚴(yán)重的時(shí)候,還會(huì)出現(xiàn)內(nèi)存異常的現(xiàn)象。
今天我給大家推薦一款性能更好的 Excel 導(dǎo)入導(dǎo)出工具:EasyExcel,希望對(duì)大家有所幫助!
easyexcel 是阿里開(kāi)源的一款 Excel導(dǎo)入導(dǎo)出工具,具有處理速度快、占用內(nèi)存小、使用方便的特點(diǎn),底層邏輯也是基于 apache poi 進(jìn)行二次開(kāi)發(fā)的,目前的應(yīng)用也是非常廣!
相比 EasyPoi,EasyExcel 的處理數(shù)據(jù)性能非常高,讀取 75M (46W行25列) 的Excel,僅需使用 64M 內(nèi)存,耗時(shí) 20s,極速模式還可以更快!
廢話也不多說(shuō)了,下面直奔主題!
二、實(shí)踐
在 SpringBoot 項(xiàng)目中集成 EasyExcel 其實(shí)非常簡(jiǎn)單,僅需一個(gè)依賴(lài)即可。
com.alibaba
easyexcel
3.0.5
EasyExcel 的導(dǎo)出導(dǎo)入支持兩種方式進(jìn)行處理
- 第一種是通過(guò)實(shí)體類(lèi)注解方式來(lái)生成文件和反解析文件數(shù)據(jù)映射成對(duì)象
- 第二種是通過(guò)動(dòng)態(tài)參數(shù)化生成文件和反解析文件數(shù)據(jù)
下面我們以用戶信息的導(dǎo)出導(dǎo)入為例,分別介紹兩種處理方式。
簡(jiǎn)單導(dǎo)出
首先,我們只需要?jiǎng)?chuàng)建一個(gè)UserEntity用戶實(shí)體類(lèi),然后添加對(duì)應(yīng)的注解字段即可,示例代碼如下:
public class UserWriteEntity {
@ExcelProperty(value = "姓名")
private String name;
@ExcelProperty(value = "年齡")
private int age;
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
@ExcelProperty(value = "操作時(shí)間")
private Date time;
//set、get...
}
然后,使用 EasyExcel 提供的EasyExcel工具類(lèi),即可實(shí)現(xiàn)文件的導(dǎo)出。
public static void main(String[] args) throws FileNotFoundException {
List dataList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
UserWriteEntity userEntity = new UserWriteEntity();
userEntity.setName("張三" + i);
userEntity.setAge(20 + i);
userEntity.setTime(new Date(System.currentTimeMillis() + i));
dataList.add(userEntity);
}
//定義文件輸出位置
FileOutputStream outputStream = new FileOutputStream(new File("/Users/panzhi/Documents/easyexcel-export-user1.xlsx"));
EasyExcel.write(outputStream, UserWriteEntity.class).sheet("用戶信息").doWrite(dataList);
}
運(yùn)行程序,打開(kāi)文件內(nèi)容結(jié)果!
簡(jiǎn)單導(dǎo)入
這種簡(jiǎn)單固定表頭的 Excel 文件,如果想要讀取文件數(shù)據(jù),操作也很簡(jiǎn)單。
以上面的導(dǎo)出文件為例,使用 EasyExcel 提供的EasyExcel工具類(lèi),即可來(lái)實(shí)現(xiàn)文件內(nèi)容數(shù)據(jù)的快速讀取,示例代碼如下:
首先創(chuàng)建讀取實(shí)體類(lèi)
/**
* 讀取實(shí)體類(lèi)
*/
public class UserReadEntity {
@ExcelProperty(value = "姓名")
private String name;
/**
* 強(qiáng)制讀取第三個(gè) 這里不建議 index 和 name 同時(shí)用,要么一個(gè)對(duì)象只用index,要么一個(gè)對(duì)象只用name去匹配
*/
@ExcelProperty(index = 1)
private int age;
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
@ExcelProperty(value = "操作時(shí)間")
private Date time;
//set、get...
}
然后讀取文件數(shù)據(jù),并封裝到對(duì)象里面
public static void main(String[] args) throws FileNotFoundException {
//同步讀取文件內(nèi)容
FileInputStream inputStream = new FileInputStream(new File("/Users/panzhi/Documents/easyexcel-user1.xls"));
List list = EasyExcel.read(inputStream).head(UserReadEntity.class).sheet().doReadSync();
System.out.println(JSONArray.toJSONString(list));
}
運(yùn)行程序,輸出結(jié)果如下:
[{"age":20,"name":"張三0","time":1616920360000},{"age":21,"name":"張三1","time":1616920360000},{"age":22,"name":"張三2","time":1616920360000},{"age":23,"name":"張三3","time":1616920360000},{"age":24,"name":"張三4","time":1616920360000},{"age":25,"name":"張三5","time":1616920360000},{"age":26,"name":"張三6","time":1616920360000},{"age":27,"name":"張三7","time":1616920360000},{"age":28,"name":"張三8","time":1616920360000},{"age":29,"name":"張三9","time":1616920360000}]
動(dòng)態(tài)自由導(dǎo)出導(dǎo)入
在實(shí)際使用開(kāi)發(fā)中,我們不可能每來(lái)一個(gè) excel 導(dǎo)入導(dǎo)出需求,就編寫(xiě)一個(gè)實(shí)體類(lèi),很多業(yè)務(wù)需求需要根據(jù)不同的字段來(lái)動(dòng)態(tài)導(dǎo)入導(dǎo)出,沒(méi)辦法基于實(shí)體類(lèi)注解的方式來(lái)讀取文件或者寫(xiě)入文件。
因此,基于EasyExcel提供的動(dòng)態(tài)參數(shù)化生成文件和動(dòng)態(tài)監(jiān)聽(tīng)器讀取文件方法,我們可以單獨(dú)封裝一套動(dòng)態(tài)導(dǎo)出導(dǎo)出工具類(lèi),省的我們每次都需要重新編寫(xiě)大量重復(fù)工作,以下就是小編我在實(shí)際使用過(guò)程,封裝出來(lái)的工具類(lèi),在此分享給大家!
- 首先,我們可以編寫(xiě)一個(gè)動(dòng)態(tài)導(dǎo)出工具類(lèi)
public class DynamicEasyExcelExportUtils {
private static final Logger log = LoggerFactory.getLogger(DynamicEasyExcelExportUtils.class);
private static final String DEFAULT_SHEET_NAME = "sheet1";
/**
* 動(dòng)態(tài)生成導(dǎo)出模版(單表頭)
* @param headColumns 列名稱(chēng)
* @return excel文件流
*/
public static byte[] exportTemplateExcelFile(List headColumns){
List> excelHead = Lists.newArrayList();
headColumns.forEach(columnName -> { excelHead.add(Lists.newArrayList(columnName)); });
byte[] stream = createExcelFile(excelHead, new ArrayList<>());
return stream;
}
/**
* 動(dòng)態(tài)生成模版(復(fù)雜表頭)
* @param excelHead 列名稱(chēng)
* @return
*/
public static byte[] exportTemplateExcelFileCustomHead(List> excelHead){
byte[] stream = createExcelFile(excelHead, new ArrayList<>());
return stream;
}
/**
* 動(dòng)態(tài)導(dǎo)出文件(通過(guò)map方式計(jì)算)
* @param headColumnMap 有序列頭部
* @param dataList 數(shù)據(jù)體
* @return
*/
public static byte[] exportExcelFile(LinkedHashMap headColumnMap, List
- 然后,編寫(xiě)一個(gè)動(dòng)態(tài)導(dǎo)入工具類(lèi)
/**
* 創(chuàng)建一個(gè)文件讀取監(jiān)聽(tīng)器
*/
public class DynamicEasyExcelListener extends AnalysisEventListener


咨詢
建站咨詢
