EasyExcel是一個基于Java的、快速、簡潔、解決大檔案記憶體溢位的Excel處理工具,
他能讓你在不用考慮性能、記憶體的等因素的情況下,快速完成Excel的讀、寫等功能,
快速入門
匯入依賴
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.1.1</version>
</dependency>
寫 Excel
1.以物體類映射想要寫入 Excel 的資料
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ExcelEntity {
@ExcelProperty("字串標題")
private String string;
@ExcelProperty("日期標題")
private Date date;
@ExcelProperty("數字標題")
private Double doubleData;
@ExcelIgnore
private String ignore;
}
注解說明
-
ExcelProperty:定義排版
-
value:字串標題
-
index:指定資料所在列,從0起算
@ExcelProperty(value = "https://www.cnblogs.com/V-Notes/archive/2023/06/02/字串標題", index = 0) -
復雜頭寫入
@ExcelProperty({"主標題", "字串標題"})
-
-
DateTimeFormat:定義時間格式
@DateTimeFormat("yyyy年MM月dd日HH時mm分ss秒") @ExcelProperty("日期標題") private Date date; -
NumberFormat:定義數字格式
@NumberFormat("#.##%") // 用百分比表示 @ExcelProperty(value = "https://www.cnblogs.com/V-Notes/archive/2023/06/02/數字標題") private Double doubleData; -
ColumnWidth:列寬
-
ContentRowHeight:行高
-
HeadRowHeight:表頭行高(寫在類名上)
-
ContentLoopMerge:合并單元格
// 這一列 每隔2行 合并單元格 @ContentLoopMerge(eachRow = 2) @ExcelProperty("字串標題") private String string; -
ExcelIgnore:忽略這個欄位
2.將資料存盤到物體類中
private List<DemoData> data() {
List<DemoData> list = ListUtils.newArrayList();
for (int i = 0; i < 10; i++) {
DemoData data = https://www.cnblogs.com/V-Notes/archive/2023/06/02/new DemoData();
data.setString("字串" + i);
data.setDate(new Date());
data.setDoubleData(0.56);
list.add(data);
}
return list;
}
3.資料寫入 Excel
方法1:在資料量不大的情況下可以使用(5000以內,具體也要看實際情況),資料量大參照 重復多次寫入
@Test
public void simpleWrite() {
// 創建一個檔案的絕對路徑
String fileName = "D:\\demo1.xlsx";
// write(): 引數一:檔案路徑 引數二:要寫的資料對應的物體位元組碼
// sheet(): excel表格名稱
// doWrite(): 要寫的資料,是一個集合
EasyExcel.write(fileName, ExcelEntity.class).sheet("模板").doWrite(() -> {
// 分頁查詢資料
return data();
});
}
方法2:
@Test
public void simpleWrite() {
String fileName = "D:\\demo1.xlsx";
// 這里 需要指定寫用哪個class去寫,然后寫到第一個sheet,名字為模板 然后檔案流會自動關閉
// 如果這里想使用03 則 傳入excelType引數即可
EasyExcel.write(fileName, ExcelEntity.class).sheet("模板").doWrite(data());
}
方法3:
@Test
public void simpleWrite3() {
String fileName = "D:\\demo1.xlsx";
// 這里 需要指定寫用哪個class去寫
try (ExcelWriter excelWriter = EasyExcel.write(fileName, ExcelEntity.class).build()) {
WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
excelWriter.write(data(), writeSheet);
}
}
4.忽略或指定匯出
忽略
// 根據用戶傳入欄位 假設我們要忽略 date
Set<String> excludeColumnFiledNames = new HashSet<String>();
excludeColumnFiledNames.add("date");
// 這里 需要指定寫用哪個class去寫,然后寫到第一個sheet,名字為模板 然后檔案流會自動關閉
EasyExcel.write(fileName, ExcelEntity.class).excludeColumnFiledNames(excludeColumnFiledNames).sheet("模板")
.doWrite(data());
指定匯出
// 根據用戶傳入欄位 假設我們只要匯出 date
Set<String> includeColumnFiledNames = new HashSet<String>();
includeColumnFiledNames.add("date");
// 這里 需要指定寫用哪個class去寫,然后寫到第一個sheet,名字為模板 然后檔案流會自動關閉
EasyExcel.write(fileName, ExcelEntity.class).includeColumnFiledNames(includeColumnFiledNames).sheet("模板")
.doWrite(data());
5.在同一 sheet 續寫
@Test
public void repeatedWrite() {
String fileName = "D:\\demo1.xlsx";
// 這里 需要指定寫用哪個class去寫
try (ExcelWriter excelWriter = EasyExcel.write(fileName, ExcelEntity.class).build()) {
// 這里注意 如果同一個sheet只要創建一次
WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
// 去呼叫寫入,這里我呼叫了五次,實際使用時根據資料庫分頁的總的頁數來
for (int i = 0; i < 5; i++) {
// 分頁去資料庫查詢資料 這里可以去資料庫查詢每一頁的資料
List<ExcelEntity> data = https://www.cnblogs.com/V-Notes/archive/2023/06/02/data();
excelWriter.write(data, writeSheet);
}
}
}
6.同一個物件寫到不同的sheet
@Test
public void repeatedWrite() {
String fileName = "D:\\demo1.xlsx";
// 這里 指定檔案
try (ExcelWriter excelWriter = EasyExcel.write(fileName, ExcelEntity.class).build()) {
// 去呼叫寫入,這里我呼叫了五次,實際使用時根據資料庫分頁的總的頁數來,這里最侄訓寫到5個sheet里面
for (int i = 0; i < 5; i++) {
// 每次都要創建writeSheet 這里注意必須指定sheetNo 而且sheetName必須不一樣
WriteSheet writeSheet = EasyExcel.writerSheet(i, "模板" + i).build();
// 分頁去資料庫查詢資料 這里可以去資料庫查詢每一頁的資料
List<ExcelEntity> data = https://www.cnblogs.com/V-Notes/archive/2023/06/02/data();
excelWriter.write(data, writeSheet);
}
}
}
7.不同的物件寫到不同的sheet
@Test
public void repeatedWrite() {
String fileName = "D:\\demo1.xlsx";
// 這里 指定檔案
try (ExcelWriter excelWriter = EasyExcel.write(fileName).build()) {
// 去呼叫寫入,這里我呼叫了五次,實際使用時根據資料庫分頁的總的頁數來,這里最侄訓寫到5個sheet里面
for (int i = 0; i < 5; i++) {
// 每次都要創建writeSheet 這里注意必須指定sheetNo 而且sheetName必須不一樣,這里注意DemoData.class 可以每次都變,我這里為了方便 所以用的同一個class
// 實際上可以一直變
WriteSheet writeSheet = EasyExcel.writerSheet(i, "模板" + i).head(ExcelEntity.class).build();
// 分頁去資料庫查詢資料 這里可以去資料庫查詢每一頁的資料
List<ExcelEntity> data = https://www.cnblogs.com/V-Notes/archive/2023/06/02/data();
excelWriter.write(data, writeSheet);
}
}
}
讀 Excel
1.以物體類映射想要讀取的 Excel 資料
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ExcelEntity {
private String string;
private Date date;
private Double doubleData;
}
2.持久層
/**
* 假設這個是你的DAO存盤,當然還要這個類讓spring管理,當然你不用需要存盤,也不需要這個類,
**/
public class ExcelDAO {
public void save(List<ExcelEntity> list) {
// 如果是mybatis,盡量別直接呼叫多次insert,自己寫一個mapper里面新增一個方法batchInsert,所有資料一次性插入
}
}
3.監聽器
// 有個很重要的點 ExcelEntityListener 不能被spring管理,要每次讀取excel都要new,然后里面用到spring可以構造方法傳進去
public class ExcelEntityListener implements ReadListener<ExcelEntity> {
/**
* 每隔5條存盤資料庫,實際使用中可以100條,然后清理list ,方便記憶體回收
*/
private static final int BATCH_COUNT = 100;
/**
* 快取的資料
*/
private List<ExcelEntity> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
/**
* 假設這個是一個DAO,當然有業務邏輯這個也可以是一個service,當然如果不用存盤這個物件沒用,
*/
private ExcelDAO excelDAO;
public ExcelEntityListener() {
// 這里是demo,所以隨便new一個,實際使用如果到了spring,請使用下面的有參建構式
excelDAO = new ExcelDAO();
}
/**
* 如果使用了spring,請使用這個構造方法,每次創建Listener的時候需要把spring管理的類傳進來
*
* @param excelDAO
*/
public ExcelEntityListener(ExcelDAO excelDAO) {
this.excelDAO = excelDAO;
}
/**
* 這個每一條資料決議都會來呼叫
*
* @param data one row value. Is is same as {@link AnalysisContext#readRowHolder()}
* @param context
*/
@Override
public void invoke(ExcelEntity data, AnalysisContext context) {
cachedDataList.add(data);
// 達到BATCH_COUNT了,需要去存盤一次資料庫,防止資料幾萬條資料在記憶體,容易OOM
if (cachedDataList.size() >= BATCH_COUNT) {
saveData();
// 存盤完成清理 list
cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
}
}
/**
* 所有資料決議完成了 都會來呼叫
*
* @param context
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 這里也要保存資料,確保最后遺留的資料也存盤到資料庫
saveData();
}
/**
* 加上存盤資料庫
*/
private void saveData() {
excelDAO.save(cachedDataList);
}
}
4.讀取 Excel 資料
@Test
public void simpleRead() {
// 寫法1:JDK8+ ,不用額外寫一個DemoDataListener
// since: 3.0.0-beta1
String fileName = "D:\\damo1.xlsx";
// 這里默認每次會讀取100條資料 然后回傳過來 直接呼叫使用資料就行
// 具體需要回傳多少行可以在`PageReadListener`的建構式設定
EasyExcel.read(fileName, ExcelEntity.class, new PageReadListener<ExcelEntity>(dataList -> {
for (ExcelEntity demoData : dataList) {
log.info("讀取到一條資料{}", JSON.toJSONString(demoData));
}
})).sheet().doRead();
// 寫法2:
// 匿名內部類 不用額外寫一個DemoDataListener
fileName = "D:\\damo1.xlsx";
// 這里 需要指定讀用哪個class去讀,然后讀取第一個sheet 檔案流會自動關閉
EasyExcel.read(fileName, ExcelEntity.class, new ReadListener<ExcelEntity>() {
/**
* 單次快取的資料量
*/
public static final int BATCH_COUNT = 100;
/**
*臨時存盤
*/
private List<ExcelEntity> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
@Override
public void invoke(ExcelEntity data, AnalysisContext context) {
cachedDataList.add(data);
if (cachedDataList.size() >= BATCH_COUNT) {
saveData();
// 存盤完成清理 list
cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
saveData();
}
/**
* 加上存盤資料庫
*/
private void saveData() {
log.info("{}條資料,開始存盤資料庫!", cachedDataList.size());
log.info("存盤資料庫成功!");
}
}).sheet().doRead();
// 有個很重要的點 DemoDataListener 不能被spring管理,要每次讀取excel都要new,然后里面用到spring可以構造方法傳進去
// 寫法3:
fileName = "D:\\damo1.xlsx";
// 這里 需要指定讀用哪個class去讀,然后讀取第一個sheet 檔案流會自動關閉
EasyExcel.read(fileName, ExcelEntity.class, new ExcelEntityListener()).sheet().doRead();
// 寫法4
fileName = "D:\\damo1.xlsx";
// 一個檔案一個reader
try (ExcelReader excelReader = EasyExcel.read(fileName, ExcelEntity.class, new ExcelEntityListener()).build()) {
// 構建一個sheet 這里可以指定名字或者no
ReadSheet readSheet = EasyExcel.readSheet(0).build();
// 讀取一個sheet
excelReader.read(readSheet);
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/554066.html
標籤:其他
下一篇:返回列表
