日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
SpringBoot實現(xiàn)Excel自由導入導出,性能強的離譜,用起來還特優(yōu)雅

一、簡介

在實際的業(yè)務系統(tǒng)開發(fā)過程中,操作 Excel 實現(xiàn)數(shù)據(jù)的導入導出基本上是個非常常見的需求。

之前,我們有介紹一款非常好用的工具:EasyPoi,有讀者提出在數(shù)據(jù)量大的情況下,EasyPoi 會占用內存大,性能不夠好,嚴重的時候,還會出現(xiàn)內存異常的現(xiàn)象。

今天我給大家推薦一款性能更好的 Excel 導入導出工具:EasyExcel,希望對大家有所幫助!

easyexcel 是阿里開源的一款 Excel導入導出工具,具有處理速度快、占用內存小、使用方便的特點,底層邏輯也是基于 apache poi 進行二次開發(fā)的,目前的應用也是非常廣!

相比 EasyPoi,EasyExcel 的處理數(shù)據(jù)性能非常高,讀取 75M (46W行25列) 的Excel,僅需使用 64M 內存,耗時 20s,極速模式還可以更快!

廢話也不多說了,下面直奔主題!

二、實踐

在 SpringBoot 項目中集成 EasyExcel 其實非常簡單,僅需一個依賴即可。



com.alibaba
easyexcel
3.0.5


EasyExcel 的導出導入支持兩種方式進行處理

  • 第一種是通過實體類注解方式來生成文件和反解析文件數(shù)據(jù)映射成對象
  • 第二種是通過動態(tài)參數(shù)化生成文件和反解析文件數(shù)據(jù)

下面我們以用戶信息的導出導入為例,分別介紹兩種處理方式。

簡單導出

首先,我們只需要創(chuàng)建一個UserEntity用戶實體類,然后添加對應的注解字段即可,示例代碼如下:

public class UserWriteEntity {

@ExcelProperty(value = "姓名")
private String name;

@ExcelProperty(value = "年齡")
private int age;

@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
@ExcelProperty(value = "操作時間")
private Date time;

//set、get...
}

然后,使用 EasyExcel 提供的EasyExcel工具類,即可實現(xiàn)文件的導出。

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);
}

運行程序,打開文件內容結果!

簡單導入

這種簡單固定表頭的 Excel 文件,如果想要讀取文件數(shù)據(jù),操作也很簡單。

以上面的導出文件為例,使用 EasyExcel 提供的EasyExcel工具類,即可來實現(xiàn)文件內容數(shù)據(jù)的快速讀取,示例代碼如下:

首先創(chuàng)建讀取實體類

/**
* 讀取實體類
*/
public class UserReadEntity {

@ExcelProperty(value = "姓名")
private String name;
/**
* 強制讀取第三個 這里不建議 index 和 name 同時用,要么一個對象只用index,要么一個對象只用name去匹配
*/
@ExcelProperty(index = 1)
private int age;

@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
@ExcelProperty(value = "操作時間")
private Date time;

//set、get...
}

然后讀取文件數(shù)據(jù),并封裝到對象里面

public static void main(String[] args) throws FileNotFoundException {
//同步讀取文件內容
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));
}

運行程序,輸出結果如下:

[{"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}]

動態(tài)自由導出導入

在實際使用開發(fā)中,我們不可能每來一個 excel 導入導出需求,就編寫一個實體類,很多業(yè)務需求需要根據(jù)不同的字段來動態(tài)導入導出,沒辦法基于實體類注解的方式來讀取文件或者寫入文件。

因此,基于EasyExcel提供的動態(tài)參數(shù)化生成文件和動態(tài)監(jiān)聽器讀取文件方法,我們可以單獨封裝一套動態(tài)導出導出工具類,省的我們每次都需要重新編寫大量重復工作,以下就是小編我在實際使用過程,封裝出來的工具類,在此分享給大家!

  • 首先,我們可以編寫一個動態(tài)導出工具類
public class DynamicEasyExcelExportUtils {

private static final Logger log = LoggerFactory.getLogger(DynamicEasyExcelExportUtils.class);

private static final String DEFAULT_SHEET_NAME = "sheet1";

/**
* 動態(tài)生成導出模版(單表頭)
* @param headColumns 列名稱
* @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;
}

/**
* 動態(tài)生成模版(復雜表頭)
* @param excelHead 列名稱
* @return
*/
public static byte[] exportTemplateExcelFileCustomHead(List> excelHead){
byte[] stream = createExcelFile(excelHead, new ArrayList<>());
return stream;
}

/**
* 動態(tài)導出文件(通過map方式計算)
* @param headColumnMap 有序列頭部
* @param dataList 數(shù)據(jù)體
* @return
*/
public static byte[] exportExcelFile(LinkedHashMap headColumnMap, List> dataList){
//獲取列名稱
List> excelHead = new ArrayList<>();
if(MapUtils.isNotEmpty(headColumnMap)){
//key為匹配符,value為列名,如果多級列名用逗號隔開
headColumnMap.entrySet().forEach(entry -> {
excelHead.add(Lists.newArrayList(entry.getValue().split(",")));
});
}
List> excelRows = new ArrayList<>();
if(MapUtils.isNotEmpty(headColumnMap) && CollectionUtils.isNotEmpty(dataList)){
for (Map dataMap : dataList) {
List rows = new ArrayList<>();
headColumnMap.entrySet().forEach(headColumnEntry -> {
if(dataMap.containsKey(headColumnEntry.getKey())){
Object data = dataMap.get(headColumnEntry.getKey());
rows.add(data);
}
});
excelRows.add(rows);
}
}
byte[] stream = createExcelFile(excelHead, excelRows);
return stream;
}


/**
* 生成文件(自定義頭部排列)
* @param rowHeads
* @param excelRows
* @return
*/
public static byte[] customerExportExcelFile(List> rowHeads, List> excelRows){
//將行頭部轉成easyexcel能識別的部分
List> excelHead = transferHead(rowHeads);
return createExcelFile(excelHead, excelRows);
}

/**
* 生成文件
* @param excelHead
* @param excelRows
* @return
*/
private static byte[] createExcelFile(List> excelHead, List> excelRows){
try {
if(CollectionUtils.isNotEmpty(excelHead)){
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
EasyExcel.write(outputStream).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
.head(excelHead)
.sheet(DEFAULT_SHEET_NAME)
.doWrite(excelRows);
return outputStream.toByteArray();
}
} catch (Exception e) {
log.error("動態(tài)生成excel文件失敗,headColumns:" + JSONArray.toJSONString(excelHead) + ",excelRows:" + JSONArray.toJSONString(excelRows), e);
}
return null;
}

/**
* 將行頭部轉成easyexcel能識別的部分
* @param rowHeads
* @return
*/
public static List> transferHead(List> rowHeads){
//將頭部列進行反轉
List> realHead = new ArrayList<>();
if(CollectionUtils.isNotEmpty(rowHeads)){
Map> cellMap = new LinkedHashMap<>();
//遍歷行
for (List cells : rowHeads) {
//遍歷列
for (int i = 0; i < cells.size(); i++) {
if(cellMap.containsKey(i)){
cellMap.get(i).add(cells.get(i));
} else {
cellMap.put(i, Lists.newArrayList(cells.get(i)));
}
}
}
//將列一行一行加入realHead
cellMap.entrySet().forEach(item -> realHead.add(item.getValue()));
}
return realHead;
}

/**
* 導出文件測試
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
//導出包含數(shù)據(jù)內容的文件(方式一)
LinkedHashMap headColumnMap = Maps.newLinkedHashMap();
headColumnMap.put("className","班級");
headColumnMap.put("name","學生信息,姓名");
headColumnMap.put("sex","學生信息,性別");
List> dataList = new ArrayList<>();
for (int i = 0; i < 5; i++) {
Map dataMap = Maps.newHashMap();
dataMap.put("className", "一年級");
dataMap.put("name", "張三" + i);
dataMap.put("sex", "男");
dataList.add(dataMap);
}
byte[] stream1 = exportExcelFile(headColumnMap, dataList);
FileOutputStream outputStream1 = new FileOutputStream(new File("/Users/panzhi/Documents/easyexcel-export-user5.xlsx"));
outputStream1.write(stream1);
outputStream1.close();


//導出包含數(shù)據(jù)內容的文件(方式二)
//頭部,第一層
List head1 = new ArrayList<>();
head1.add("第一行頭部列1");
head1.add("第一行頭部列1");
head1.add("第一行頭部列1");
head1.add("第一行頭部列1");
//頭部,第二層
List head2 = new ArrayList<>();
head2.add("第二行頭部列1");
head2.add("第二行頭部列1");
head2.add("第二行頭部列2");
head2.add("第二行頭部列2");
//頭部,第三層
List head3 = new ArrayList<>();
head3.add("第三行頭部列1");
head3.add("第三行頭部列2");
head3.add("第三行頭部列3");
head3.add("第三行頭部列4");

//封裝頭部
List> allHead = new ArrayList<>();
allHead.add(head1);
allHead.add(head2);
allHead.add(head3);

//封裝數(shù)據(jù)體
//第一行數(shù)據(jù)
List data1 = Lists.newArrayList(1,1,1,1);
//第二行數(shù)據(jù)
List data2 = Lists.newArrayList(2,2,2,2);
List> allData = Lists.newArrayList(data1, data2);

byte[] stream2 = customerExportExcelFile(allHead, allData);
FileOutputStream outputStream2 = new FileOutputStream(new File("/Users/panzhi/Documents/easyexcel-export-user6.xlsx"));
outputStream2.write(stream2);
outputStream2.close();


}
}

  • 然后,編寫一個動態(tài)導入工具類
/**
* 創(chuàng)建一個文件讀取監(jiān)聽器
*/
public class DynamicEasyExcelListener extends AnalysisEventListener> {
private static final Logger LOGGER = LoggerFactory.getLogger(UserDataListener.class);
/**
* 表頭數(shù)據(jù)(存儲所有的表頭數(shù)據(jù))
*/
private List> headList = new ArrayList<>();
/**
* 數(shù)
文章名稱:SpringBoot實現(xiàn)Excel自由導入導出,性能強的離譜,用起來還特優(yōu)雅
本文網(wǎng)址:http://m.5511xx.com/article/dhjhdhs.html