EasyExcel入門


作者: 故事我忘了
個人微信公眾號: 程序猿的月光寶盒

因為最近在項目中用到了阿里巴巴的easy excel,然后去b

站學習了一下,看了黑馬的公開課教程,然后自己再clone了easy excel的源碼,

以下是b站的課堂筆記分享,基本夠用...

對應的github地址

對應的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。

總體上來說,簡單寫法重度依賴內存,復雜寫法學習成本高。

特點

  1. 功能強大

  2. 代碼書寫冗余繁雜

  3. 讀寫大文件耗費內存較大,容易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多一點)

圖片

  • 在上層做了模型轉換的封裝,讓使用者更加簡單方便

特點

  1. 在數據模型層面進行了封裝,使用簡單
  2. 重寫了07版本的Excel的解析代碼,降低內存消耗,能有效避免OOM
  3. 只能操作Excel
  4. 不能讀取圖片

二、快速入門--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文件

調用EasyExcelAPI讀取的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 指定需要讀表格的 列頭行數。默認有一行頭,也就是認為第二行開始起為數據。

  • headclazz二選一。讀取文件頭對應的列表,會根據列表匹配數據。建議使用clas,就是文件中每一行數據對應的代碼中的實體類型。

  • clazzhead二選一。讀取文件的頭對應的class,也可以使用注解。如果兩個都不指定,則會讀取全部數據。

  • autoTrim 字符串、表頭等數據自動trim

  • password 讀的時候是否需要使用密碼

4、ReadWorkbook(工作簿對象)參數

  • excelType 當前excel的類型,讀取時會自動判斷,無需設置。
  • inputStreamfile二選一。建議使用file。
  • fileinputStream二選一。讀取文件的文件。
  • autoCloseStream 自動關閉流。
  • readCache 默認小於5M用 內存,超過5M會使用 EhCache,不建議使用這個參數。
  • useDefaultListener @since 2.1.4 默認會加入ModelBuildEventListener 來幫忙轉換成傳入class的對象,設置成false后將不會協助轉換對象,自定義的監聽器會接收到Map<Integer,CellData>對象,如果還想繼續接聽到class對象,請調用readListener方法,加入自定義的beforeListenerModelBuildEventListener、 自定義的afterListener即可。

5、ReadSheet(工作表對象)參數

  • sheetNo 需要讀取Sheet的編號,建議使用這個來指定讀取哪個Sheet
  • sheetName 根據名字去匹配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、寫入時通用參數

WriteWorkbookWriteSheet都會有的參數,如果為空,默認使用上級。

  • converter 轉換器,默認加載了很多轉換器。也可以自定義。

  • writeHandler 寫的處理器。可以實現WorkbookWriteHandler,SheetWriteHandler,RowWriteHandler,CellWriteHandler,在寫入excel的不同階段會調用,對使用者透明不可見。

  • relativeHeadRowIndex 距離多少行后開始。也就是開頭空幾行

  • needHead 是否導出頭

  • headclazz二選一。寫入文件的頭列表,建議使用class。

  • clazzhead二選一。寫入文件的頭對應的class,也可以使用注解。

  • autoTrim 字符串、表頭等數據自動trim

8、WriteWorkbook(工作簿對象)參數

  • excelType 當前excel的類型,默認為xlsx

  • outputStreamfile二選一。寫入文件的流

  • fileoutputStream二選一。寫入的文件

  • templateInputStream 模板的文件流

  • templateFile 模板文件

  • autoCloseStream 自動關閉流。

  • password 寫的時候是否需要使用密碼

  • useDefaultStyle 寫的時候是否是使用默認頭

9、WriteSheet(工作表對象)參數

  • sheetNo 需要寫入的編號。默認0

  • sheetName 需要些的Sheet名稱,默認同sheetNo


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM