一篇文章帶你玩轉(zhuǎn)Java EasyExcel(Excel報(bào)表必學(xué))
一:EasyExcel簡介
1.EasyExcel是一個(gè)基于Java的簡單、省內(nèi)存的讀寫Excel的開源項(xiàng)目。在盡可能節(jié)約內(nèi)存的情況下支持讀寫百M(fèi)的Excel。
2.Java解析、生成Excel比較有名的框架有Apache poi、jxl。但他們都存在一個(gè)嚴(yán)重的問題就是非常的耗內(nèi)存,poi有一套SAX模式的API可以一定程度的解決一些內(nèi)存溢出的問題,但POI還是有一些缺陷,比如07版Excel解壓縮以及解壓后存儲(chǔ)都是在內(nèi)存中完成的,內(nèi)存消耗依然很大。easyexcel重寫了poi對07版Excel的解析,一個(gè)3M的excel用POI sax解析依然需要100M左右內(nèi)存,改用easyexcel可以降低到幾M,并且再大的excel也不會(huì)出現(xiàn)內(nèi)存溢出;03版依賴POI的sax模式,在上層做了模型轉(zhuǎn)換的封裝,讓使用者更加簡單方便。
3.github地址:github官網(wǎng)
二: EasyExcel使用
1.EasyExcel相關(guān)依賴
1)添加maven依賴
<dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.2.3</version> </dependency>
2)添加jar包
asm-4.2.jar cglib-3.1.jar commons-codec-1.10.jar commons-collections4-4.1.jar curvesapi-1.04.jar easyexcel-2.2.3.jar ehcache-3.4.0.jar poi-3.17.jar poi-ooxml-3.17.jar poi-ooxml-schemas-3.17.jar slf4j-api-1.7.26.jar stax-api-1.0.1.jar xmlbeans-2.6.0.jar
2.寫Excel
/**
* 創(chuàng)建User類,用于構(gòu)建向Excel表格中寫數(shù)據(jù)的類型;
* @ExcelProperty:這個(gè)注解是EasyExcel提供,用于生成Excel表格頭
*/
public class User {
@ExcelProperty("用戶編號(hào)")
private Integer userId;
@ExcelProperty("姓名")
private String userName;
@ExcelProperty("性別")
private String gender;
@ExcelProperty("工資")
private Double salary;
@ExcelProperty("入職時(shí)間")
private Date hireDate;
//setter/getter方法
}
@ExcelProperty:這個(gè)注解是EasyExcel提供,用于生成Excel表格頭,取名字
1)最簡單的寫(方式一)
/**
* 向Excel文檔中寫數(shù)據(jù)(方式一)
* 最簡單的寫
*/
@Test
public void writeExcel1() {
//創(chuàng)建文件保存的位置,以及文件名
String fileName="user1.xlsx";
/**
* 構(gòu)建要寫入的數(shù)據(jù)
* User類是一個(gè)自定義的特殊類,專門用來構(gòu)建向Excel中寫數(shù)據(jù)的類型類
* @ExcelProperty是easyexcel提供的注解,用來定義表格的頭部
*/
List<User> data = new ArrayList<>();
User user = new User(2001,"李雷","男",1000.123,new Date());
data.add(user);
//將數(shù)據(jù)寫到Excel的第一個(gè)sheet標(biāo)簽中,并且給sheet標(biāo)簽起名字
EasyExcel.write(fileName,User.class).sheet("用戶信息").doWrite(data);
//文件流會(huì)自動(dòng)關(guān)閉
}
2)最簡單的寫(方式二)
/**
* 向Excel文檔中寫數(shù)據(jù)(方式二)
* 最簡單的寫
*/
@Test
public void writeExcel2() {
//創(chuàng)建文件保存的位置,以及文件名
String fileName="user2.xlsx";
/**
* 構(gòu)建要寫入的數(shù)據(jù)
* User類是一個(gè)自定義的特殊類,專門用來構(gòu)建向Excel中寫數(shù)據(jù)的類型類
* @ExcelProperty是easyexcel提供的注解,用來定義表格的頭部
*/
List<User> data = new ArrayList<>();
User user = new User(2001,"李雷","男",1000.123,new Date());
data.add(user);
//創(chuàng)建Excel寫對象
ExcelWriter excelWriter = EasyExcel.write(fileName, User.class).build();
//創(chuàng)建sheet對象
WriteSheet writeSheet = EasyExcel.writerSheet("用戶信息").build();
//將數(shù)據(jù)寫到sheet標(biāo)簽中
excelWriter.write(data, writeSheet);
//關(guān)閉流,文件流手動(dòng)關(guān)閉
excelWriter.finish();
}
3)將類中某幾個(gè)字段排除掉,不寫入Excel中
/**
* 向Excel文檔中寫數(shù)據(jù)
* 將User類中的某幾個(gè)屬性字段排除
*/
@Test
public void writeExcel3() {
//創(chuàng)建文件保存的位置,以及文件名
String fileName="user3.xlsx";
/**
* 構(gòu)建要寫入的數(shù)據(jù)
* User類是一個(gè)自定義的特殊類,專門用來構(gòu)建向Excel中寫數(shù)據(jù)的類型類
* @ExcelProperty是easyexcel提供的注解,用來定義表格的頭部
*/
List<User> data = new ArrayList<>();
User user = new User(2001,"李雷","男",1000.123,new Date());
data.add(user);
//構(gòu)建要排除掉的列
Set<String> excludeColumnFiledNames = new HashSet<>();
//排除掉hireDate和userName字段
excludeColumnFiledNames.add("hireDate");
excludeColumnFiledNames.add("userName");
EasyExcel.write(fileName, User.class).excludeColumnFiledNames(excludeColumnFiledNames).sheet("abc").doWrite(data);
}
4)只向表格中導(dǎo)出指定某幾個(gè)字段
/**
* 向Excel文檔中寫數(shù)據(jù)
* 指定將User類中的某幾個(gè)字段導(dǎo)出
*/
@Test
public void writeExcel4() {
//創(chuàng)建文件保存的位置,以及文件名
String fileName="user4.xlsx";
/**
* 構(gòu)建要寫入的數(shù)據(jù)
* User類是一個(gè)自定義的特殊類,專門用來構(gòu)建向Excel中寫數(shù)據(jù)的類型類
* @ExcelProperty是easyexcel提供的注解,用來定義表格的頭部
*/
List<User> data = new ArrayList<>();
User user = new User(2001,"李雷","男",1000.123,new Date());
data.add(user);
//構(gòu)建要導(dǎo)出的列
Set<String> includeColumnFiledNames = new HashSet<>();
//要導(dǎo)出hireDate和userName字段
includeColumnFiledNames.add("hireDate");
includeColumnFiledNames.add("userName");
EasyExcel.write(fileName, User.class).includeColumnFiledNames(includeColumnFiledNames).sheet("abc").doWrite(data);
}
5)插入指定的列
將Java對象中指定的屬性,插入到Excel表格中的指定的列(在Excel中進(jìn)行列排序)
寫Excel的Java對象類型
public class IndexUser {
/**
* value: 設(shè)置Excel中列頭的名字 index: 設(shè)置Excel中將數(shù)據(jù)插入指定的列(列排序) eg: value="姓名" index=2 :
* 將姓名的列頭設(shè)置在Excel表格的第三列
*/
@ExcelProperty(value = "用戶編號(hào)", index = 0)
private Integer userId;
@ExcelProperty(value = "姓名", index = 2)
private String userName;
@ExcelProperty(value = "入職時(shí)間", index = 1)
private Date hireDate;
}
向Excel中寫數(shù)據(jù)
/**
* 插入指定列
* Java類中有三個(gè)屬性
* 我現(xiàn)在要將這三個(gè)屬性的數(shù)據(jù)保存到Excel表格中
* 并且自定義在Excel中的列順序
*/
@Test
public void writeExcel5() {
//創(chuàng)建文件保存的位置,以及文件名
String fileName="user5.xlsx";
/**
* 構(gòu)建要寫入的數(shù)據(jù)
*/
List<IndexUser> data = new ArrayList<>();
IndexUser user = new IndexUser(1001,"楓橋夜泊",new Date());
data.add(user);
EasyExcel.write(fileName, IndexUser.class).sheet("abc").doWrite(data);
}
6)復(fù)雜頭數(shù)據(jù)寫入
寫Excel的Java對象類型
/**
* 構(gòu)建復(fù)雜頭信息數(shù)據(jù)的類
*/
public class ComplexHeadUser {
/**
* {"用戶主題1","用戶編號(hào)"}這種遇到格式設(shè)置多級主題
* 第一個(gè)參數(shù)為一級主題(第一行)
* 第二個(gè)參數(shù)為二級主題(第二行)
* 如果一級主題名稱相同,那么他們會(huì)合并單元格
*/
@ExcelProperty({"用戶主題1","用戶編號(hào)"})
private Integer userId;
@ExcelProperty({"用戶主題2","用戶名稱"})
private String userName;
@ExcelProperty({"用戶主題3","入職時(shí)間"})
private Date hireDate;
}
向Excel中寫數(shù)據(jù)
/**
* 寫入復(fù)雜頭信息到Excel
*/
@Test
public void writeExcel6() {
//創(chuàng)建文件保存的位置,以及文件名
String fileName="user6.xlsx";
/**
* 構(gòu)建要寫入的數(shù)據(jù)
*/
List<ComplexHeadUser> data = new ArrayList<>();
ComplexHeadUser user = new ComplexHeadUser(1001,"楓橋夜泊",new Date());
data.add(user);
EasyExcel.write(fileName, ComplexHeadUser.class).sheet("abc").doWrite(data);
}
7)重復(fù)寫到Excel的同一個(gè)sheet中
/**
* 重復(fù)寫到同一個(gè)sheet中
*/
@Test
public void writeExcel7() {
//創(chuàng)建文件保存的位置,以及文件名
String fileName="user7.xlsx";
//構(gòu)建數(shù)據(jù)
List<User> data = new ArrayList<>();
User user1 = new User(2001,"李雷1","男",1000.123,new Date());
User user2 = new User(2002,"李雷2","男",1000.123,new Date());
User user3 = new User(2003,"李雷3","男",1000.123,new Date());
User user4 = new User(2004,"李雷4","男",1000.123,new Date());
data.add(user1);
data.add(user2);
data.add(user3);
data.add(user4);
//創(chuàng)建ExcelWriter對對象并設(shè)置用哪個(gè)Class(數(shù)據(jù)類型)去寫
ExcelWriter excelWriter = EasyExcel.write(fileName, User.class).build();
//創(chuàng)建sheet
WriteSheet writeSheet = EasyExcel.writerSheet("用戶信息").build();
//模擬重復(fù)寫入,模擬重復(fù)寫入5次
for (int i = 0; i < 5; i++) {
excelWriter.write(data, writeSheet);
}
//關(guān)閉流
excelWriter.finish();
}
8)重復(fù)的寫到Excel的不同sheet中
/**
* 重復(fù)寫到不同sheet中
*/
@Test
public void writeExcel8() {
//創(chuàng)建文件保存的位置,以及文件名
String fileName="user8.xlsx";
//構(gòu)建數(shù)據(jù)
List<User> data = new ArrayList<>();
User user1 = new User(2001,"李雷1","男",1000.123,new Date());
User user2 = new User(2002,"李雷2","男",1000.123,new Date());
User user3 = new User(2003,"李雷3","男",1000.123,new Date());
User user4 = new User(2004,"李雷4","男",1000.123,new Date());
data.add(user1);
data.add(user2);
data.add(user3);
data.add(user4);
//創(chuàng)建ExcelWriter對對象并設(shè)置用哪個(gè)Class(數(shù)據(jù)類型)去寫
ExcelWriter excelWriter = EasyExcel.write(fileName, User.class).build();
//模擬重復(fù)寫入,模擬重復(fù)寫入5次
for (int i = 0; i < 5; i++) {
//創(chuàng)建sheet(因?yàn)閷懭氲讲煌膕heet,所以需要多次創(chuàng)建sheet)
//WriteSheet writeSheet = EasyExcel.writerSheet(i,"用戶信息"+i).build(); //用下面的格式也可以
WriteSheet writeSheet = EasyExcel.writerSheet("用戶信息"+i).build();
excelWriter.write(data, writeSheet);
}
//關(guān)閉流
excelWriter.finish();
}
9)日期、數(shù)字類型格式化
對于日期和數(shù)字有時(shí)候我們需要對其展示的樣式進(jìn)行格式化,easyexcel提供了一下 注解 @DateTimeFormat : 日期格式化 @NumberFormat : 數(shù)字格式化(小數(shù)或者百分?jǐn)?shù))
寫Excel的Java對象類型
/**
* 創(chuàng)建User類,用于構(gòu)建向Excel表格中寫數(shù)據(jù)的類型;
* @ExcelProperty:這個(gè)注解是EasyExcel提供,用于生成Excel表格頭
*/
public class User {
@ExcelProperty("用戶編號(hào)")
private Integer userId;
@ExcelProperty("姓名")
private String userName;
@ExcelProperty("性別")
private String gender;
//格式化小數(shù)類型,如果是百分?jǐn)?shù)那么定義為 #.##% 比如:9.12%
@NumberFormat("#.##")
@ExcelProperty("工資")
private Double salary;
//格式化時(shí)間
@DateTimeFormat("yyyy年MM月dd日 HH時(shí)mm分ss秒")
@ExcelProperty("入職時(shí)間")
private Date hireDate;
}
向Excel中寫數(shù)據(jù)
/**
* 日期、數(shù)字格式化
*/
@Test
public void writeExcel9() {
//創(chuàng)建文件保存的位置,以及文件名
String fileName="user9.xlsx";
//構(gòu)建數(shù)據(jù)
List<User> data = new ArrayList<>();
User user1 = new User(2001,"李雷1","男",1000.12223,new Date());
User user2 = new User(2002,"李雷2","男",1000.12223,new Date());
User user3 = new User(2003,"李雷3","男",1000.12223,new Date());
User user4 = new User(2004,"李雷4","男",1000.13323,new Date());
data.add(user1);
data.add(user2);
data.add(user3);
data.add(user4);
EasyExcel.write(fileName, User.class).sheet("用戶信息").doWrite(data);
}
10)寫入圖片到Excel
寫Excel的Java對象類型
/**
* 構(gòu)建向Excel中寫圖片的類 支持5種數(shù)據(jù)類型的圖片類型
* 1. 圖片可以是一個(gè)File格式
* 2. 圖片可以是一個(gè)InputStream輸入流的方式
* 3. 圖片可以是一個(gè)byte[]數(shù)組的方式
* 4. 圖片可以是 一個(gè)網(wǎng)絡(luò)的java.net.URL對象方式
* 5. 圖片也可以是一個(gè)String類型方式(當(dāng)是String類型是,需要StringImageConverter類型轉(zhuǎn)換器)
*/
@ContentRowHeight(100) // 內(nèi)容高度
@ColumnWidth(100 / 8) // 列寬
public class ImageData {
// 使用抽象文件表示一個(gè)圖片
private File file;
// 使用輸入流保存一個(gè)圖片
private InputStream inputStream;
/**
* 當(dāng)使用String類型保存一個(gè)圖片的時(shí)候需要使用StringImageConverter轉(zhuǎn)換器
*/
@ExcelProperty(converter = StringImageConverter.class)
private String string;
// 使用二進(jìn)制數(shù)據(jù)保存為一個(gè)圖片
private byte[] byteArray;
// 使用網(wǎng)絡(luò)鏈接保存一個(gè)圖片
private URL url;
}
向Excel中寫數(shù)據(jù)
/**
* 將圖片寫入到Excel表格中
* EasyExcel提供了5種數(shù)據(jù)格式進(jìn)行圖片寫入
* @throws IOException
*/
@Test
public void writeExcel10() throws IOException {
//創(chuàng)建文件保存的位置,以及文件名
String fileName="user10.xlsx";
List<ImageData> list = new ArrayList<ImageData>();
ImageData imageData = new ImageData();
//根據(jù)File寫入
imageData.setFile(new File("imgs/img.png"));
//根據(jù)InputStream寫入
imageData.setInputStream(new FileInputStream("imgs/img.png"));
//根據(jù)String類型寫入
imageData.setString("imgs/img.png");
/*
* 使用二進(jìn)制方式寫入步驟:
* 1. 獲取文件大小
* 2. 讀成二進(jìn)制流
*/
File file = new File("imgs/img.png");
//創(chuàng)建一個(gè)指定大小的二進(jìn)制數(shù)組
byte[] byteArray = new byte[(int)file.length()];
FileInputStream in = new FileInputStream(file);
//將文件流寫入到二進(jìn)制數(shù)組中
in.read(byteArray, 0, (int)file.length());
imageData.setByteArray(byteArray);
//只用網(wǎng)絡(luò)鏈接
imageData.setUrl(new URL("https://pics5.baidu.com/feed/e850352ac65c10384dcf6805a7540815b17e890b.jpeg?token=46fd105a95d8754d3daf93de7e8a7f6f"));
list.add(imageData);
EasyExcel.write(fileName, ImageData.class).sheet().doWrite(list);
//關(guān)閉輸入流
in.close();
}
11)設(shè)置寫入Excel的列寬行高設(shè)置
寫Excel的Java對象類型
@ContentRowHeight(30) //設(shè)置內(nèi)容高度
@HeadRowHeight(40) //設(shè)置標(biāo)題高度
@ColumnWidth(25) //設(shè)置列寬
public class WidthAndHeightData {
@ExcelProperty("字符串標(biāo)題")
private String string;
@ExcelProperty("日期標(biāo)題")
private Date date;
@ColumnWidth(50) //設(shè)置列寬(可以修飾類,也可以修飾具體屬性)
@ExcelProperty("數(shù)字標(biāo)題")
private Double doubleData;
}
向Excel中寫數(shù)據(jù)
/**
* 設(shè)置Excel的列寬行高
*/
@Test
public void writeExcel11(){
//創(chuàng)建文件保存的位置,以及文件名
String fileName="user11.xlsx";
//構(gòu)建數(shù)據(jù)
List<WidthAndHeightData> list = new ArrayList<WidthAndHeightData>();
WidthAndHeightData wahd = new WidthAndHeightData();
wahd.setString("小明");
wahd.setDoubleData(200.12);
wahd.setDate(new Date());
list.add(wahd);
//寫數(shù)據(jù)
EasyExcel.write(fileName, WidthAndHeightData.class).sheet("信息").doWrite(list);
}
12)通過注解形式設(shè)置寫入Excel的樣式
寫Excel的Java對象類型
//頭背景設(shè)置成紅色 IndexedColors.RED.getIndex()
@HeadStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 10)
//頭字體設(shè)置成20
@HeadFontStyle(fontHeightInPoints = 20)
//內(nèi)容的背景設(shè)置成綠色 IndexedColors.GREEN.getIndex()
@ContentStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 17)
//內(nèi)容字體設(shè)置成20
@ContentFontStyle(fontHeightInPoints = 20)
public class DemoStyleData {
// 字符串的頭背景設(shè)置成粉紅 IndexedColors.PINK.getIndex()
@HeadStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 14)
// 字符串的頭字體設(shè)置成20
@HeadFontStyle(fontHeightInPoints = 30)
// 字符串的內(nèi)容的背景設(shè)置成天藍(lán) IndexedColors.SKY_BLUE.getIndex()
@ContentStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 40)
// 字符串的內(nèi)容字體設(shè)置成20
@ContentFontStyle(fontHeightInPoints = 30)
@ExcelProperty("字符串標(biāo)題")
private String string;
@ExcelProperty("日期標(biāo)題")
private Date date;
@ExcelProperty("數(shù)字標(biāo)題")
private Double doubleData;
}
向Excel中寫數(shù)據(jù)
/**
* 注解形式設(shè)置Excel樣式
*/
@Test`在這里插入代碼片`
public void writeExcel12(){
//創(chuàng)建文件保存的位置,以及文件名
String fileName="user12.xlsx";
//構(gòu)建數(shù)據(jù)
List<DemoStyleData> list = new ArrayList<>();
DemoStyleData dsld = new DemoStyleData();
dsld.setDate(new Date());
dsld.setDoubleData(200.12);
dsld.setString("韓梅梅");
list.add(dsld);
EasyExcel.write(fileName, DemoStyleData.class).sheet("信息").doWrite(list);
}
13)合并單元格
寫Excel的Java對象類型
/*
* @OnceAbsoluteMerge: 指定從哪一行開始,哪一行結(jié)束,哪一列開始,哪一列結(jié)束,進(jìn)行合并單元格
* firstRowIndex : 起始行索引 從0開始
* lastRowIndex : 結(jié)束行索引
* firstColumnIndex: 起始列索引 從0開始
* lastColumnIndex : 結(jié)束列索引
* 例如: 第2-3行,2-3列進(jìn)行合并
*/
@OnceAbsoluteMerge(firstRowIndex = 1,lastRowIndex = 2,firstColumnIndex = 1,lastColumnIndex = 2)
public class DemoMergeData {
//每隔兩行合并一次(豎著合并單元格)
//@ContentLoopMerge(eachRow = 2)
@ExcelProperty("字符串標(biāo)題")
private String string;
@ExcelProperty("日期標(biāo)題")
private Date date;
@ExcelProperty("數(shù)字標(biāo)題")
private Double doubleData;
}
向Excel中寫數(shù)據(jù)
/**
* 合并單元格
*/
@Test
public void writeExcel13(){
//創(chuàng)建文件保存的位置,以及文件名
String fileName="user13.xlsx";
//構(gòu)建數(shù)據(jù)
List<DemoMergeData> list = new ArrayList<>();
DemoMergeData dmd = new DemoMergeData();
dmd.setDate(new Date());
dmd.setDoubleData(200.12);
dmd.setString("韓梅梅");
DemoMergeData dmd2 = new DemoMergeData();
dmd2.setDate(new Date());
dmd2.setDoubleData(200.12);
dmd2.setString("韓梅梅");
DemoMergeData dmd3 = new DemoMergeData();
dmd3.setDate(new Date());
dmd3.setDoubleData(200.12);
dmd3.setString("韓梅梅");
DemoMergeData dmd4 = new DemoMergeData();
dmd4.setDate(new Date());
dmd4.setDoubleData(200.12);
dmd4.setString("韓梅梅");
DemoMergeData dmd5 = new DemoMergeData();
dmd5.setDate(new Date());
dmd5.setDoubleData(200.12);
dmd5.setString("韓梅梅");
list.add(dmd);
list.add(dmd2);
list.add(dmd3);
list.add(dmd4);
list.add(dmd5);
EasyExcel.write(fileName, DemoMergeData.class).sheet("信息").doWrite(list);
}
3.讀Excel
1)最簡單的讀取Excel
Excel表格數(shù)據(jù)類型

盛裝數(shù)據(jù)的Java對象
/**
* 承裝Excel表格數(shù)據(jù)的類
* 注意點(diǎn): Java類中的屬性的順序和Excel中的列頭的順序是相同的
*/
public class DemoData {
private String name;
private Date hireDate;
private Double salary;
}
讀取Excel數(shù)據(jù)
/*
* 最簡單的讀取Excel內(nèi)容(方式一)
* 默認(rèn)讀取Excel文件中的第一個(gè)sheet
*/
@Test
public void testRead1() {
//讀取的文件路徑
String fileName="user11.xlsx";
Class<DemoData> head = DemoData.class; //創(chuàng)建一個(gè)數(shù)據(jù)格式來承裝讀取到數(shù)據(jù)
//讀取數(shù)據(jù)
EasyExcel.read(fileName, head, new AnalysisEventListener<DemoData>() {
/**
* 解析每一條數(shù)據(jù)的時(shí)候被調(diào)用
*/
@Override
public void invoke(DemoData data, AnalysisContext context) {
//在這里操作,將解析的每一條數(shù)據(jù)保存到數(shù)據(jù)庫中,在這里可以調(diào)用數(shù)據(jù)庫
System.out.println("解析的數(shù)據(jù)為: "+data);
}
/**
* 解析完所有數(shù)據(jù)的時(shí)候被調(diào)用
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
System.out.println("數(shù)據(jù)解析完成..........");
}
}).sheet().doRead();
}
/*
* 最簡單的讀取Excel內(nèi)容(方式二)
* 默認(rèn)讀取Excel文件中的第一個(gè)sheet
*/
@Test
public void testRead2() {
//讀取的文件路徑
String fileName="user11.xlsx";
Class<DemoData> head = DemoData.class; //創(chuàng)建一個(gè)數(shù)據(jù)格式來承裝讀取到數(shù)據(jù)
//創(chuàng)建ExcelReader對象
ExcelReader excelReader = EasyExcel.read(fileName, head, new AnalysisEventListener<DemoData>() {
@Override
public void invoke(DemoData data, AnalysisContext context) {
System.out.println("讀取到的數(shù)據(jù)為:"+data);
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
System.out.println("數(shù)據(jù)解析已完成");
}
}).build();
//創(chuàng)建sheet對象,并讀取Excel的第1個(gè)sheet(下標(biāo)從0開始)
ReadSheet readSheet = EasyExcel.readSheet(0).build();
excelReader.read(readSheet);
//關(guān)閉流操作,在讀取文件時(shí)會(huì)創(chuàng)建臨時(shí)文件,如果不關(guān)閉,磁盤爆掉
excelReader.finish();
}
2)根據(jù)Excel中指定的列名或者列的下標(biāo)讀取指定列的數(shù)據(jù)
盛裝數(shù)據(jù)的Java對象
public class IndexOrNameData {
/**
* 強(qiáng)制讀取第三個(gè) 這里不建議 index 和 name 同時(shí)用,要么一個(gè)對象只用index,要么一個(gè)對象只用name去匹配
*/
@ExcelProperty(index = 2)
private Double doubleData;
/**
* 用名字去匹配,這里需要注意,如果名字重復(fù),會(huì)導(dǎo)致只有一個(gè)字段讀取到數(shù)據(jù)
*/
@ExcelProperty("字符串標(biāo)題")
private String string;
@ExcelProperty("日期標(biāo)題")
private Date date;
}
讀取Excel數(shù)據(jù)操作
/*
* 根據(jù)名稱或者下標(biāo)獲取指定的Excel表格數(shù)據(jù)
*/
@Test
public void testRead3() {
//讀取的文件路徑
String fileName="user11.xlsx";
Class<IndexOrNameData> head = IndexOrNameData.class; //創(chuàng)建一個(gè)數(shù)據(jù)格式來承裝讀取到數(shù)據(jù)
//讀取數(shù)據(jù)
EasyExcel.read(fileName, head, new AnalysisEventListener<IndexOrNameData>() {
/**
* 解析每一條數(shù)據(jù)的時(shí)候被調(diào)用
*/
@Override
public void invoke(IndexOrNameData data, AnalysisContext context) {
//在這里操作,將解析的每一條數(shù)據(jù)保存到數(shù)據(jù)庫中,在這里可以調(diào)用數(shù)據(jù)庫
System.out.println("解析的數(shù)據(jù)為: "+data);
}
/**
* 解析完所有數(shù)據(jù)的時(shí)候被調(diào)用
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
System.out.println("數(shù)據(jù)解析完成..........");
}
}).sheet().doRead();
}
3)格式化Excel中的數(shù)據(jù)格式(例如時(shí)間)
盛裝數(shù)據(jù)的Java對象
/**
* 定義需要被格式化的字段
* 如果使用@NumberFormat("#.##")注解,建議數(shù)據(jù)類型采用String,如果使用double可能不能被格式化
*/
public class ConverterData {
@NumberFormat("#.#")
@ExcelProperty("數(shù)字標(biāo)題")
private String salary;
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
@ExcelProperty("日期標(biāo)題")
private Date hireDate;
}
讀取Excel數(shù)據(jù)操作
/*
* 格式化Excel中的數(shù)據(jù)格式(例如時(shí)間)
*/
@Test
public void testRead4() {
//讀取的文件路徑
String fileName="user11.xlsx";
Class<ConverterData> head = ConverterData.class; //創(chuàng)建一個(gè)數(shù)據(jù)格式來承裝讀取到數(shù)據(jù)
//讀取數(shù)據(jù)
EasyExcel.read(fileName, head, new AnalysisEventListener<ConverterData>() {
/**
* 解析每一條數(shù)據(jù)的時(shí)候被調(diào)用
*/
@Override
public void invoke(ConverterData data, AnalysisContext context) {
//在這里操作,將解析的每一條數(shù)據(jù)保存到數(shù)據(jù)庫中,在這里可以調(diào)用數(shù)據(jù)庫
System.out.println("解析的數(shù)據(jù)為: "+data);
}
/**
* 解析完所有數(shù)據(jù)的時(shí)候被調(diào)用
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
System.out.println("數(shù)據(jù)解析完成..........");
}
}).sheet().doRead();
}
4)讀取多個(gè)或者全部的Sheet
盛裝數(shù)據(jù)的Java對象
/**
* 承裝Excel表格數(shù)據(jù)的類
* 注意點(diǎn): Java類中的屬性的順序和Excel中的列頭的順序是相同的
*/
public class DemoData {
private String name;
private Date hireDate;
private Double salary;
}
讀取Excel數(shù)據(jù)操作
/*
* 讀取Excel中的多個(gè)或者全部sheet
*/
@Test
public void testRead5() {
//讀取的文件路徑
String fileName="user11.xlsx";
Class<DemoData> head = DemoData.class; //創(chuàng)建一個(gè)數(shù)據(jù)格式來承裝讀取到數(shù)據(jù)
/**
* 讀取全部sheet
*/
EasyExcel.read(fileName, head, new AnalysisEventListener<DemoData>() {
@Override
public void invoke(DemoData data, AnalysisContext context) {
// 每解析一條數(shù)據(jù)被調(diào)用一次
System.out.println("解析的數(shù)據(jù)為: "+data);
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 數(shù)據(jù)解析完成之后被調(diào)用
System.out.println("數(shù)據(jù)解析完成......");
}
}).doReadAll();
System.out.println("============================================================");
/**
* 讀取其中的某幾個(gè)sheet
*/
//構(gòu)建ExcelReader對象
ExcelReader excelReader = EasyExcel.read(fileName).build();
//創(chuàng)建想要獲取的sheet對象
ReadSheet sheet1 = EasyExcel.readSheet(0).head(DemoData.class).registerReadListener(new AnalysisEventListener<DemoData>() {
@Override
public void invoke(DemoData data, AnalysisContext context) {
// 每解析一條數(shù)據(jù)被調(diào)用一次
System.out.println("解析的數(shù)據(jù)為: "+data);
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 數(shù)據(jù)解析完成之后被調(diào)用
System.out.println("數(shù)據(jù)解析完成......");
}
}).build();
ReadSheet sheet2 = EasyExcel.readSheet(2).head(DemoData.class).registerReadListener(new AnalysisEventListener<DemoData>() {
@Override
public void invoke(DemoData data, AnalysisContext context) {
// 每解析一條數(shù)據(jù)被調(diào)用一次
System.out.println("解析的數(shù)據(jù)為: "+data);
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 數(shù)據(jù)解析完成之后被調(diào)用
System.out.println("數(shù)據(jù)解析完成......");
}
}).build();
//讀取sheet
excelReader.read(sheet1,sheet2);
//關(guān)閉
excelReader.finish();
}
4.填充Excel
1)簡單填充
創(chuàng)建Excel模板格式 填充單個(gè)屬性使用{}作為占位符,在大括號(hào)里面定義屬性名稱,如果{}想不作為占位符展示出來,可以使用反斜杠進(jìn)行轉(zhuǎn)義.

填充數(shù)據(jù)的Java類
public class FillData {
private String name;
private double number;
}
填充的代碼
/**
* 簡單的單個(gè)對象填充
*/
@Test
public void excelFull() {
//讀取模板文件
String templateFileName="templateFileName.xlsx";
//通過模板文件生成的填充之后的文件
String fullFile="fullFile.xlsx";
//構(gòu)建要填充的數(shù)據(jù)
FillData data = new FillData();
data.setName("張三");
data.setNumber(5.2);
//填充操作
EasyExcel.write(fullFile).withTemplate(templateFileName).sheet().doFill(data);
}
填充之后的效果

2)列表填充
填充數(shù)據(jù)的Java類
public class FillData {
private String name;
private double number;
}
填充的代碼
/**
* 簡單的列表對象填充
*/
@Test
public void excelFull2() {
//讀取模板文件
String templateFileName="templateFileName2.xlsx";
//通過模板文件生成的填充之后的文件
String fullFile="fullFile2.xlsx";
//構(gòu)建要填充的數(shù)據(jù)列表
List<FillData> list = new ArrayList<FillData>();
FillData data1 = new FillData();
data1.setName("張三");
data1.setNumber(5.2);
FillData data2 = new FillData();
data2.setName("張三");
data2.setNumber(5.2);
list.add(data1);
list.add(data2);
//填充操作
EasyExcel.write(fullFile).withTemplate(templateFileName).sheet().doFill(list);
}
填充之后的效果

5.Web操作(Excel上傳/下載)
1) Excel下載
HTML
<a href="${pageContext.request.contextPath }/DownLoadExcel" rel="external nofollow" >下載</a>
封裝數(shù)據(jù)的Java類
public class User {
@ExcelProperty("用戶編號(hào)")
private Integer userId;
@ExcelProperty("用戶名稱")
private String userName;
@ExcelProperty("用戶性別")
private String gender;
@ExcelProperty("創(chuàng)建時(shí)間")
private Date createTime;
}
下載操作
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/**
* EasyExcel下載步驟
*/
//設(shè)置響應(yīng)頭
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
//設(shè)置防止文件名中文亂碼
String fileName = URLEncoder.encode("中文文件名","utf-8");
response.setHeader("Content-disposition", "attachment;filename="+ fileName + ".xlsx");
//構(gòu)建寫入到Excel中的數(shù)據(jù)(此數(shù)據(jù)可以從數(shù)據(jù)庫中獲取)
List<User> users = new ArrayList<>();
User user1 = new User(1001, "李雷1", "男", new Date());
User user2 = new User(1002, "李雷2", "男", new Date());
User user3 = new User(1003, "李雷3", "男", new Date());
users.add(user1);
users.add(user2);
users.add(user3);
EasyExcel.write(response.getOutputStream(),User.class).sheet("用戶信息").doWrite(users);
}
6.Excel上傳
1)前端頁面
<form action="${pageContext.request.contextPath }/UploadExcelServlet" method="post" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit" value="上傳">
</form>
2)接收從Excel中獲取到的數(shù)據(jù)
public class User {
@ExcelProperty("用戶編號(hào)")
private Integer userId;
@ExcelProperty("用戶名稱")
private String userName;
@ExcelProperty("用戶性別")
private String gender;
@ExcelProperty("創(chuàng)建時(shí)間")
private Date createTime;
}
3)上傳操作
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload fileUpload = new ServletFileUpload(factory);
//設(shè)置單個(gè)文件為3M
fileUpload.setFileSizeMax(1024*1024*3);
//總文件大小為30M
fileUpload.setSizeMax(1024*1024*3*10);
try {
List<FileItem> list = fileUpload.parseRequest(req);
for (FileItem fileItem : list) {
//判斷是否為附件
if(!fileItem.isFormField()) {
//是附件
InputStream inputStream = fileItem.getInputStream();
EasyExcel.read(inputStream,User.class,new AnalysisEventListener<User>() {
@Override
public void doAfterAllAnalysed(AnalysisContext arg0) {
System.out.println("Excel全部讀完被執(zhí)行......");
}
@Override
public void invoke(User data, AnalysisContext arg1) {
//讀完一行就執(zhí)行一次(調(diào)用數(shù)據(jù)庫進(jìn)行插入操作)
System.out.println("解析一行: "+data);
}
}).sheet().doRead();
}else {
//普通表單
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
//上傳完成進(jìn)行轉(zhuǎn)發(fā)或者重定向
}
以上就是一篇文章帶你玩轉(zhuǎn)Java EasyExcel(Excel報(bào)表必學(xué))的詳細(xì)內(nèi)容,更多關(guān)于Java EasyExcel使用的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
一文深入分析java.lang.ClassNotFoundException異常
這篇文章主要給大家介紹了關(guān)于java.lang.ClassNotFoundException異常的相關(guān)資料,java.lang.ClassNotFoundException是Java編程時(shí)經(jīng)常會(huì)遇到的一個(gè)異常,它表示JVM在嘗試加載某個(gè)類時(shí)未能找到該類,需要的朋友可以參考下2023-10-10
Spring 中jdbcTemplate 實(shí)現(xiàn)執(zhí)行多條sql語句示例
本篇文章主要介紹了Spring 中jdbcTemplate 實(shí)現(xiàn)執(zhí)行多條sql語句示例,可以對多個(gè)表執(zhí)行多個(gè)sql語句,有興趣的可以了解一下。2017-01-01
SpringBoot中@ComponentScan的使用詳解
這篇文章主要介紹了SpringBoot中@ComponentScan的使用詳解,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
Java數(shù)據(jù)結(jié)構(gòu)之圖的領(lǐng)接矩陣詳解
圖的領(lǐng)接矩陣存儲(chǔ)方式是用兩個(gè)數(shù)組來表示圖。一個(gè)一位數(shù)組存儲(chǔ)圖中頂點(diǎn)信息,一個(gè)二維數(shù)組存儲(chǔ)圖中的邊或弧的信息。本文將為大家重點(diǎn)介紹一下數(shù)據(jù)結(jié)構(gòu)中的圖的鄰接矩陣,快來跟隨小編一起學(xué)習(xí)吧2021-11-11
java數(shù)據(jù)庫連接池的特點(diǎn)及步驟
大家好,本篇文章主要講的是數(shù)據(jù)庫連接池的特點(diǎn)及步驟,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽2021-12-12
在Spring中使用Knife4j進(jìn)行API文檔生成與管理的操作方法
Knife4j 是為Java MVC 框架(如Spring Boot、Spring MVC等)集成 Swagger 生成 API 文檔的增強(qiáng)解決方案,它基于 Swagger 的核心功能,通過定制化的前端界面和一些額外的特性,本文介紹了在Spring中使用Knife4j進(jìn)行API文檔生成與管理的操作方法,需要的朋友可以參考下2024-12-12
java異常繼承何類,運(yùn)行時(shí)異常與一般異常的區(qū)別(詳解)
下面小編就為大家?guī)硪黄猨ava異常繼承何類,運(yùn)行時(shí)異常與一般異常的區(qū)別(詳解)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-11-11

