個人微信公眾號: 程序猿的月光寶盒

因為最近在項目中用到了阿里巴巴的easy excel,然后去b
站學習了一下,看了黑馬的公開課教程,然后自己再clone了easy excel的源碼,
以下是b站的課堂筆記分享,基本夠用...
一、初識EasyExcel
1. Apache POI
先說POI
,有過報表導入導出經驗的同學,應該聽過或者使用。
Apache POI
是Apache軟件基金會的開源函式庫,提供跨平台的Java API
實現Microsoft Office
格式檔案讀寫。但是存在如下一些問題:
1.1 學習使用成本較高
對POI有過深入了解的才知道原來POI還有SAX模式(Dom解析模式)。但SAX模式相對比較復雜,excel有03和07兩種版本,兩個版本數據存儲方式截然不同,sax解析方式也各不一樣。
想要了解清楚這兩種解析方式,才去寫代碼測試,估計兩天時間是需要的。再加上即使解析完,要轉換到自己業務模型還要很多繁瑣的代碼。總體下來感覺至少需要三天,由於代碼復雜,后續維護成本巨大。
POI的SAX模式的API可以一定程度的解決一些內存溢出的問題,但是POI還是有一些缺陷,比如07版Excel解壓縮以及解壓后存儲都是在內存中完成的,內存消耗依然很大,一個3M的Excel用POI的SAX解析,依然需要100M左右內存。
1.2 POI的內存消耗較大
大部分使用POI都是使用他的userModel模式。userModel的好處是上手容易使用簡單,隨便拷貝個代碼跑一下,剩下就是寫業務轉換了,雖然轉換也要寫上百行代碼,相對比較好理解。然而userModel模式最大的問題是在於非常大的內存消耗,一個幾兆的文件解析要用掉上百兆的內存。現在很多應用采用這種模式,之所以還正常在跑一定是並發不大,並發上來后一定會OOM或者頻繁的full gc。
總體上來說,簡單寫法重度依賴內存,復雜寫法學習成本高。
特點
-
功能強大
-
代碼書寫冗余繁雜
-
讀寫大文件耗費內存較大,容易OOM
2. EasyExcel
2.1 重寫了POI對07版Excel的解析
-
EasyExcel重寫了POI對07版Excel的解析,可以把內存消耗從100M左右降低到10M以內,並且再大的Excel不會出現內存溢出,03版仍依賴POI的SAX模式。
-
下圖為64M內存1分鍾內讀取75M(46W行25列)的Excel(當然還有急速模式能更快,但是內存占用會在100M多一點)
- 在上層做了模型轉換的封裝,讓使用者更加簡單方便
特點
- 在數據模型層面進行了封裝,使用簡單
- 重寫了07版本的Excel的解析代碼,降低內存消耗,能有效避免OOM
- 只能操作Excel
- 不能讀取圖片
二、快速入門--QuickStart
0、導入依賴坐標
<!-- EasyExcel -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.1.6</version>
</dependency>
<!-- lombok 優雅編程 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency>
<!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
導入
easyexcel-2.1.6
坐標的時候,以依賴傳遞導入poi-3.17
的POI。如果 ·
1、最簡單的讀
1.1、需求、准備工作
/**
* 需求:單實體導入
* 導入Excel學員信息到系統。
* 包含如下列:姓名、性別、出生日期
* 模板詳見:杭州黑馬在線202003班學員信息.xls
*/
// 杭州黑馬在線202003班學員信息.xls文件
1.2、編寫導出數據的實體
// 基於lombok
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
/**
* 學生姓名
*/
private String name;
/**
* 學生性別
*/
private String gender;
/**
* 學生出生日期
*/
private Date birthday;
/**
* id
*/
private String id;
}
1.3、 讀取Excel
文件
調用EasyExcel
的API
讀取的Excel
文件的測試類StudentReadDemo
package com.itheima.demo;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.builder.ExcelReaderSheetBuilder;
import com.itheima.domain.Student;
import com.itheima.listener.StudentReadListener;
import java.io.FileNotFoundException;
/**
* @Author Vsunks.v
* @Date 2020/3/11 23:28
* @Description:
*/
public class StudentReadDemo {
public static void main(String[] args) throws FileNotFoundException {
// 讀取文件,讀取完之后會自動關閉
/*
pathName 文件路徑;"d:\\杭州黑馬在線202003班學員信息.xls"
head 每行數據對應的實體;Student.class
readListener 讀監聽器,每讀一樣就會調用一次該監聽器的invoke方法
sheet方法參數: 工作表的順序號(從0開始)或者工作表的名字,不傳默認為0
*/
// 封裝工作簿對象
ExcelReaderBuilder workBook = EasyExcel.read
("d:\\杭州黑馬在線202003班學員信息.xls", Student.class, new StudentReadListener());
// 封裝工作表
ExcelReaderSheetBuilder sheet1 = workBook.sheet();
// 讀取
sheet1.doRead();
}
}
讀取Excel的監聽器,用於處理讀取產生的數據
package com.itheima.listener;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.itheima.domain.Student;
/**
* @Author Vsunks.v
* @Date 2020/3/11 23:12
* @Description:
*/
public class StudentReadListener extends AnalysisEventListener<Student> {
// 每讀一樣,會調用該invoke方法一次
@Override
public void invoke(Student data, AnalysisContext context) {
System.out.println("data = " + data);
log.info(data + "保存成功");
}
// 全部讀完之后,會調用該方法
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// TODO......
}
}
2、最簡單的寫
2.1 需求、准備工作
/**
* 需求:單實體導出
* 導出多個學生對象到Excel表格
* 包含如下列:姓名、性別、出生日期
* 模板詳見:杭州黑馬在線202003班學員信息.xlsx
*/
2.2、編寫導出數據的實體
// 使用lombok
package com.itheima.domain;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ColumnWidth(20)
public class Student {
/**
* id
*/
//@ExcelProperty(value = "編號",index = 3)
@ExcelIgnore
private String id;
/**
* 學生姓名
*/
@ExcelProperty(value = "學生姓名", index = 0)
//@ColumnWidth(30)
private String name;
/**
* 學生性別
*/
@ExcelProperty(value = "學生性別", index = 2)
private String gender;
/**
* 學生出生日期
*/
@ExcelProperty(value = "學生出生日期", index = 1)
//@ColumnWidth(20)
private Date birthday;
}
2.3、 准備數據並寫入到文件
package com.itheima.demo;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.itheima.domain.Student;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @Author Vsunks.v
* @Date 2020/3/11 23:27
* @Description:
*/
public class StudentWriteDemo {
public static void main(String[] args) {
List<Student> students = initData();
/*
String pathName 寫入文件的路徑
Class head 寫入文件的對象類型
默認寫入到07的xlsx中,如果想要寫入xls,可以指定類型(待驗證)
*/
ExcelWriterBuilder workBook = EasyExcel.write("d:\\杭州黑馬學員表.xlsx", Student.class);
// sheet方法參數: 工作表的順序號(從0開始)或者工作表的名字
workBook.sheet().doWrite(students);
}
private static List<Student> initData() {
ArrayList<Student> students = new ArrayList<>();
for (int i = 0; i < 10; i++) {
Student data = new Student();
data.setName("杭州黑馬學號0" + i);
data.setBirthday(new Date());
data.setGender("男");
students.add(data);
}
return students;
}
}
3、文件上傳和下載
基於SpringMVC的文件上傳和下載
0. 導入依賴
<!-- EasyExcel -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.0.5</version>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>provided</scope>
</dependency>
<!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>1.7.2</version>
</dependency>
<!-- SpringMVC(Spring) -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<!-- 文件上傳 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
3.1 文件上傳
編寫excel中每一行對應的實體類
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
/**
* 學生姓名
*/
private String name;
/**
* 學生性別
*/
private String gender;
/**
* 學生出生日期
*/
private Date birthday;
/**
* id
*/
private String id;
}
編寫回調監聽器StudentReadListener
@Component
@Scope("prototype") // 作者要求每次讀取都要使用新的Listener
public class StudentReadListener extends AnalysisEventListener<Student> {
@Autowired
private StudentService studentService;
private final int BATCH_SAVE_NUM = 5;
ArrayList<Student> students = new ArrayList<>();
private int count = 0;
// 每讀一樣,會調用該invoke方法一次
@Override
public void invoke(Student data, AnalysisContext context) {
students.add(data);
if (++count % BATCH_SAVE_NUM == 0) {
studentService.save(students);
students.clear();
}
}
// 全部讀完之后,會調用該方法
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// TODO......
}
}
業務代碼接口StudentService和實現類StudentServiceImpl
public interface StudentService {
void save(ArrayList<Student> students);
}
@Service
public class StudentServiceImpl implements StudentService {
@Override
public void save(ArrayList<Student> students) {
System.out.println("students in service = " + students);
}
}
Spring配置文件
<!-- 組件掃描-->
<context:component-scan base-package="com.itheima"/>
SpringMVC配置文件
<!-- 組件掃描-->
<context:component-scan base-package="com.itheima.demo"/>
<!-- MVC文件上傳多部件解析器 -->
<bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
id="multipartResolver"/>
編碼讀取上傳的Excel文件
@Controller
public class WebUploadAndDownload {
/**
* 文件上傳
* 1. 編寫excel中每一行對應的實體類
* 2. 由於默認異步讀取excel,所以需要逐行讀取的回調監聽器
* 3. 開始讀取Excel
*/
@PostMapping("upload")
@ResponseBody
public String upload(MultipartFile file) throws IOException {
ExcelReaderBuilder workBook = EasyExcel.read(file.getInputStream(), Student.class, studentReadListener);
workBook.sheet().doRead();
return "success";
}
3.2 文件下載
編寫實體類並創建對象以便寫入表格
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
/**
* id
*/
@ExcelIgnore
private String id;
/**
* 學生姓名
*/
//@ExcelProperty({"學員信息表", "學生姓名"})
@ExcelProperty("學生姓名")
private String name;
/**
* 學生性別
*/
//@ExcelProperty({"學員信息表", "學生性別"})
@ExcelProperty("學生性別")
private String gender;
/**
* 學生出生日期
*/
//@ExcelProperty({"學員信息表", "學生出生日期"})
@ExcelProperty("學生出生日期")
private Date birthday;
}
// 循環生成10個學生對象
private static List<Student> initData() {
ArrayList<Student> students = new ArrayList<>();
for (int i = 0; i < 10; i++) {
Student data = new Student();
data.setName("杭州黑馬學號0" + i);
data.setBirthday(new Date());
data.setGender("男");
students.add(data);
}
return students;
}
編碼將數據寫入到響應體實現下載
public class WebUploadAndDownload {
/**
* 文件下載
* 1. 編寫實體類並創建對象以便寫入表格
* 2. 設置響應參數:文件的ContentType和文件名,同時設置編碼避免亂碼
* 3. 直接寫,內部會調用finish方法自動關閉OutputStream
*/
@GetMapping("download")
public void download(HttpServletResponse response) throws IOException {
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
// 防止中文亂碼
String fileName = URLEncoder.encode("測試", "UTF-8");
response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + fileName + ".xlsx");
ExcelWriterBuilder workBook = EasyExcel.write(response.getOutputStream(), Student.class);
ExcelWriterSheetBuilder sheet = workBook.sheet("模板");
sheet.doWrite(initData());
}
}
4、自定義單元格樣式
EasyExcel支持調整行高、列寬、背景色、字體大小等內容,但是控制方式與使用原生POI無異,比較繁瑣,不建議使用。
但是可以使用模板填充的方式,向預設樣式的表格中直接寫入數據,寫入數據的時候會保持原有樣式。
三、填充
1、填充一組數據
1.1 准備模板
Excel表格中用{} 來表示包裹要填充的變量,如果單元格文本中本來就有{
、}
左右大括號,需要在括號前面使用斜杠轉義\{
、\}
。
代碼中被填充數據的實體對象的成員變量名或被填充map集合的key需要和Excel中被{}包裹的變量名稱一致。
1.2 封裝數據
編寫封裝填充數據的類或選用Map
/**
* 使用實體類封裝填充數據
*
* 實體中成員變量名稱需要和Excel表各種{}包裹的變量名匹配
*/
@Data
public class FillData {
private String name;
private int age;
}
/**
* 生成多組數據代碼
* /
private static List<FillData> initFillData() {
ArrayList<FillData> fillDatas = new ArrayList<FillData>();
for (int i = 0; i < 10; i++) {
FillData fillData = new FillData();
fillData.setName("杭州黑馬0" + i);
fillData.setAge(10 + i);
fillDatas.add(fillData);
}
return fillDatas;
}
1.3 填充
准備數據並填充到文件
public static void main(String[] args) {
// 加載模板
InputStream templateFile = FillData.class.getClassLoader().getResourceAsStream(
"fill_data_template1" +
".xlsx");
// 寫入文件
String targetFileName = "單組數據填充.xlsx";
// 准備對象數據填充
FillData fillData = new FillData();
fillData.setName("杭州黑馬");
fillData.setAge(10);
// 生成工作簿對象
ExcelWriterBuilder workBookWriter = EasyExcel.write(targetFileName).withTemplate(templateFile);
// 獲取工作表並填充
//workBookWriter.sheet().doFill(fillData);
// 使用Map數據填充
HashMap<String, String> mapFillData = new HashMap<>();
mapFillData.put("name", "杭州黑馬Map");
mapFillData.put("age", "11");
// 獲取第一個工作表填充並自動關閉流
workBookWriter.sheet().doFill(mapFillData);
}
1.4 效果
2、填充多組數據
2.1 准備模板
Excel表格中用{.}
來表示包裹要填充的變量,如果單元格文本中本來就有{
、}
左右大括號,需要在括號前面使用斜杠轉義\{
、\}
。
代碼中被填充數據的實體對象的成員變量名或被填充map集合的key需要和Excel中被{}包裹的變量名稱一致。
2.2 封裝數據
編寫封裝填充數據的類或選用Map
// 同上
2.3 填充
准備數據並填充到文件
public static void main(String[] args) {
// 加載模板
InputStream templateFile = FillData.class.getClassLoader().getResourceAsStream(
"fill_data_template2.xlsx");
// 寫入文件
String targetFileName = "多組數據填充.xlsx";
List<FillData> fillDatas = initData();
// 生成工作簿對象
ExcelWriterBuilder workBookWriter =
EasyExcel.write(targetFileName).withTemplate(templateFile);
// 獲取第一個工作表填充並自動關閉流
workBookWriter.sheet().doFill(fillDatas);
}
3、組合填充
3.1 准備模板
即有多組數據填充,又有單一數據填充,為了避免兩者數據出現沖突覆蓋的情況,在多組填充時需要通過FillConfig
對象設置換行。
3.2 封裝數據
編寫封裝填充數據的類或選用Map
// 同上
3.3 填充
准備數據並填充到文件
public static void main(String[] args) {
// 加載模板
InputStream templateFile = FillData.class.getClassLoader().getResourceAsStream(
"fill_data_template3.xlsx");
// 目標文件
String targetFileName = "組合數據填充.xlsx";
List<FillData> fillDatas = initData();
// 生成工作簿對象
ExcelWriter excelWriter = EasyExcel.write(targetFileName).withTemplate(templateFile).build();
// 生成工作表對象
WriteSheet writeSheet = EasyExcel.writerSheet().build();
// 組合填充時,因為多組填充的數據量不確定,需要在多組填充完之后另起一行
FillConfig fillConfig = FillConfig.builder().forceNewRow(true).build();
// 填充並換行
excelWriter.fill(fillDatas, fillConfig, writeSheet);
HashMap<String, String> otherData = new HashMap<>();
otherData.put("date", "2020-03-14");
otherData.put("total", "100");
excelWriter.fill(otherData, writeSheet);
// 關閉
excelWriter.finish();
}
4、水平填充
4.1 准備模板
水平填充和多組填充模板一樣,不一樣的地方在於,填充時需要通過FillConfig
對象設置水平填充。
4.2 封裝數據
編寫封裝填充數據的類或選用Map
// 同上
4.3 填充
准備數據並填充到文件
public static void main(String[] args) {
// 加載模板
InputStream templateFile = FillData.class.getClassLoader().getResourceAsStream(
"fill_data_template4.xlsx");
// 寫入文件
String targetFileName = "easyExcelDemo\\水平數據填充.xlsx";
List<FillData> fillDatas = initData();
// 生成工作簿對象
ExcelWriter excelWriter = EasyExcel.write(targetFileName).withTemplate(templateFile).build();
// 生成工作表對象
WriteSheet writeSheet = EasyExcel.writerSheet().build();
// 組合填充時,因為多組填充的數據量不確定,需要在多組填充完之后另起一行
FillConfig fillConfig = FillConfig.builder().direction(WriteDirectionEnum.HORIZONTAL).build();
// 填充
excelWriter.fill(fillDatas, fillConfig, writeSheet);
HashMap<String, String> otherData = new HashMap<>();
otherData.put("date", "2020-03-14");
otherData.put("total", "100");
excelWriter.fill(otherData, writeSheet);
// 關閉
excelWriter.finish();
}
5、 注意事項
為了節省內存,所以沒有采用把整個文檔在內存中組織好之后再整體寫入到文件的做法,而是采用的是一行一行寫入的方式,不能實現刪除和移動行,也不支持備注寫入。多組數據寫入的時候,如果需要新增行,只能在最后一行增加,不能在中間位置添加。
6、填充綜合練習
見report_template.xlsx
/**
* reprot綜合練習
*/
@Test
public void test06() {
InputStream templateInputStream = this.getClass().getClassLoader().getResourceAsStream(
"report_template.xlsx");
// 目標文件
String targetFile = "模板寫入6-report.xlsx";
// 寫入workbook對象
ExcelWriter workBook =
EasyExcel.write(targetFile, FillData.class).withTemplate(templateInputStream).build();
WriteSheet sheet = EasyExcel.writerSheet().build();
// 填充配置,開啟組合填充換行
//FillConfig fillConfig = FillConfig.builder().forceNewRow(true).build();
// ****** 准備數據 *******
// 日期
HashMap<String, String> dateMap = new HashMap<String, String>();
dateMap.put("date", "2020-03-16");
// 總會員數
HashMap<String, String> totalCountMap = new HashMap<String, String>();
dateMap.put("totalCount", "1000");
// 新增員數
HashMap<String, String> increaseCountMap = new HashMap<String, String>();
dateMap.put("increaseCount", "100");
// 本周新增會員數
HashMap<String, String> increaseCountWeekMap = new HashMap<String, String>();
dateMap.put("increaseCountWeek", "50");
// 本月新增會員數
HashMap<String, String> increaseCountMonthMap = new HashMap<String, String>();
dateMap.put("increaseCountMonth", "100");
// 新增會員數據
List<Student> students = initData();
// **** 准備數據結束****
// 寫入統計數據
workBook.fill(dateMap, sheet);
workBook.fill(totalCountMap, sheet);
workBook.fill(increaseCountMap, sheet);
workBook.fill(increaseCountWeekMap, sheet);
workBook.fill(increaseCountMonthMap, sheet);
// 寫入新增會員
workBook.fill(students, sheet);
workBook.finish();
}
四、常用API及注解
1、常用類
- EasyExcel 入口類,用於構建開始各種操作;
- ExcelReaderBuilder 構建出一個ReadWorkbook對象,即一個工作簿對象,對應的是一個Excel文件;
- ExcelWriterBuilder 構建出一個WriteWorkbook對象,即一個工作簿對象,對應的是一個Excel文件;
- ExcelReaderSheetBuilder 構建出一個ReadSheet對象,即一個工作表的對象,對應的Excel中的每個sheet,一個工作簿可以有多個工作表;
- ExcelWriterSheetBuilder 構建出一WriteSheet對象,即一個工作表的對象,對應的Excel中的每個sheet,一個工作簿可以有多個工作表;
- ReadListener 在每一行讀取完畢后都會調用ReadListener來處理數據,我們可以把調用service的代碼可以寫在其invoke方法內部;
- WriteHandler 在每一個操作包括創建單元格、創建表格等都會調用WriteHandler來處理數據,對使用者透明不可見;
- 所有配置都是繼承的 Workbook的配置會被Sheet繼承。所以在用EasyExcel設置參數的時候,在EasyExcel…sheet()方法之前作用域是整個sheet,之后針對單個sheet。
2、讀取時的注解
@ExcelProperty
使用位置:標准作用在成員變量上
可選屬性:
屬性名 | 含義 | 說明 |
---|---|---|
index | 對應Excel表中的列數 | 默認-1,建議指定時從0開始 |
value | 對應Excel表中的列頭 | |
converter | 成員變量轉換器 | 自定義轉換器需要實Converter接口 |
使用效果:index屬性可以指定當前字段對應excel中的哪一列,可以根據列名value去匹配,也可以不寫。
如果不使用@ExcelProperty注解,成員變量從上到下的順序,對應表格中從左到右的順序;
使用建議:要么全部不寫,要么全部用index,要么全部用名字去匹配,盡量不要三個混着用。
代碼演示:
// 1. 修改成員變量順序讀取Excel表格
// 2. 修改index屬性值讀取Excel表格
// 3. 修改value屬性值讀取Excel表格
@ExcelIgnore
標注在成員變量上,默認所有字段都會和excel去匹配,加了這個注解會忽略該字段
代碼演示:
// 4. 忽略id成員變量值讀取Excel表格
@DateTimeFormat
標注在成員變量上,日期轉換,代碼中用String類型的成員變量
去接收excel中日期格式的數據
會調用這個注解。里面的value
參照java.text.SimpleDateFormat
// 5. 按照指定的格式寫入Excel內容
@NumberFormat
標注在成員變量上,數字轉換,代碼中用String類型的成員變量
去接收excel數字格式的數據
會調用這個注解。里面的value
參照java.text.DecimalFormat
@ExcelIgnoreUnannotated
標注在類上。
不標注該注解時,默認類中所有成員變量都會參與讀寫,無論是否在成員變量上加了@ExcelProperty
的注解。
標注該注解后,類中的成員變量如果沒有標注@ExcelProperty
注解將不會參與讀寫。
3、 讀取時通用參數
ReadWorkbook
,ReadSheet
都會有的參數,如果為空,默認使用上級。
-
converter
轉換器,默認加載了很多轉換器。也可以自定義。 -
readListener
監聽器,在讀取數據的過程中會不斷的調用監聽器。 -
headRowNumber
指定需要讀表格的 列頭行數。默認有一行頭,也就是認為第二行開始起為數據。 -
head
與clazz
二選一。讀取文件頭對應的列表,會根據列表匹配數據。建議使用clas,就是文件中每一行數據對應的代碼中的實體類型。 -
clazz
與head
二選一。讀取文件的頭對應的class,也可以使用注解。如果兩個都不指定,則會讀取全部數據。 -
autoTrim
字符串、表頭等數據自動trim -
password
讀的時候是否需要使用密碼
4、ReadWorkbook(工作簿對象)參數
excelType
當前excel的類型,讀取時會自動判斷,無需設置。inputStream
與file
二選一。建議使用file。file
與inputStream
二選一。讀取文件的文件。autoCloseStream
自動關閉流。readCache
默認小於5M用 內存,超過5M會使用EhCache
,不建議使用這個參數。useDefaultListener
@since 2.1.4
默認會加入ModelBuildEventListener
來幫忙轉換成傳入class
的對象,設置成false
后將不會協助轉換對象,自定義的監聽器會接收到Map<Integer,CellData>
對象,如果還想繼續接聽到class
對象,請調用readListener
方法,加入自定義的beforeListener
、ModelBuildEventListener
、 自定義的afterListener
即可。
5、ReadSheet(工作表對象)參數
sheetNo
需要讀取Sheet的編號,建議使用這個來指定讀取哪個SheetsheetName
根據名字去匹配Sheet,excel 2003不支持根據名字去匹配
6、寫入時的注解解釋
@ExcelProperty
使用位置:標准作用在成員變量上
可選屬性:
屬性名 | 含義 | 說明 |
---|---|---|
index | 對應Excel表中的列數 | 默認-1,指定時建議從0開始 |
value | 對應Excel表中的列頭 | |
converter | 成員變量轉換器 | 自定義轉換器需要實Converter接口 |
使用效果:index
指定寫到第幾列,如果不指定則根據成員變量位置排序;
value
指定寫入的列頭,如果不指定則使用成員變量的名字作為列頭;
如果要設置復雜的頭,可以為value指定多個值。
代碼演示:
// 5. 為《杭州黑馬學員表.xlsx》文件中學生信息設置一個統一的表頭“杭州黑馬學員信息表”
其他注解:
基本和讀取時一致
-
@ContentRowHeight() 標注在類上或屬性上,指定內容行高
-
@HeadRowHeight() 標注在類上或屬性上,指定列頭行高
-
@ColumnWidth() 標注在類上或屬性上,指定列寬
-
ExcelIgnore` 默認所有字段都會寫入excel,這個注解會忽略這個字段
-
DateTimeFormat
日期轉換,將Date
寫到excel會調用這個注解。里面的value
參照java.text.SimpleDateFormat
-
NumberFormat
數字轉換,用Number
寫excel會調用這個注解。里面的value
參照java.text.DecimalFormat
-
ExcelIgnoreUnannotated
默認不加ExcelProperty
的注解的都會參與讀寫,加了不會參與
7、寫入時通用參數
WriteWorkbook
、WriteSheet
都會有的參數,如果為空,默認使用上級。
-
converter
轉換器,默認加載了很多轉換器。也可以自定義。 -
writeHandler
寫的處理器。可以實現WorkbookWriteHandler
,SheetWriteHandler
,RowWriteHandler
,CellWriteHandler
,在寫入excel的不同階段會調用,對使用者透明不可見。 -
relativeHeadRowIndex
距離多少行后開始。也就是開頭空幾行 -
needHead
是否導出頭 -
head
與clazz
二選一。寫入文件的頭列表,建議使用class。 -
clazz
與head
二選一。寫入文件的頭對應的class,也可以使用注解。 -
autoTrim
字符串、表頭等數據自動trim
8、WriteWorkbook(工作簿對象)參數
-
excelType
當前excel的類型,默認為xlsx
-
outputStream
與file
二選一。寫入文件的流 -
file
與outputStream
二選一。寫入的文件 -
templateInputStream
模板的文件流 -
templateFile
模板文件 -
autoCloseStream
自動關閉流。 -
password
寫的時候是否需要使用密碼 -
useDefaultStyle
寫的時候是否是使用默認頭
9、WriteSheet(工作表對象)參數
-
sheetNo
需要寫入的編號。默認0 -
sheetName
需要些的Sheet名稱,默認同sheetNo