11Easy Excel学习笔记

         Easy Excel学习笔记

1 Easy Excel简介

1.1 Easy Excel介绍

​ EasyExcel是一个基于Java的简单的、省内存的读写Excel的开源项目。

​ 在尽可能节约内存的情况下支持读写百M的Excel。

​ github地址: https://github.com/alibaba/easyexcel

image-20211228211016867

JAVA解析Excel工具EasyExcel

Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。

easyexcel重写了poi对07版Excel的解析,一个3M的excel用POI sax解析依然需要100M左右内存,改用easyexcel可以降低到几M,并且再大的excel也不会出现内存溢出;03版依赖POI的sax模式,在上层做了模型转换的封装,让使用者更加简单方便.

64M内存20秒读取75M(46W行25列)的Excel(3.0.2+版本)

1.2 Easy POI和Easy Excel对比

Easy POI:

image-20211228212557219

Easy Excel:

image-20211228212310677

(1)这两者都是引用Apache的poi 但是区别就是两者的解析不同
(2)Easy POI的解析方式是dom解析,把结果一次都读入内存操作,这样的操作平时是不会有问题的,但是并发量上来的时候就会出现OOM
(3)而阿里的Easy Excel 运用的SAX的解析方式,明显降低了内存,但是速率下降

2 环境搭建

maven依赖

<dependency>
    <groupId>com.alibaba</groupId>
     <artifactId>easyexcel</artifactId>
     <version>2.2.3</version>yuryyyyy
</dependency>

3 注解

3.1 @ExcelProperty

@ExcelProperty 这个注解的作用是描述设置Excel的表头

#常用属性
value      [String[]]  列名
index      [int]     列中的顺序
converter  [StringImageConverter.class] 当使用String类型保存一个图片的时候需要使用StringImageConverter转换器
@ExcelProperty("姓名")
private  String userName;

@ExcelProperty(converter = StringImageConverter.class)
private  String string;

3.2 @DateTimeFormat

​ 日期格式化

@DateTimeFormat("yyyy年MM月dd日")  //日期格式
@ExcelProperty(value="工资",index = 4)
private Double salary;

3.2 @NumberFormat

​ 数字格式化

@NumberFormat("#.##%")    //数字格式  小数点后2位
@ExcelProperty(value="工资",index = 4)
private Double salary;

3 读取Excel

3.1 最简单的读取Excel方式一

user13.xlsx

image-20211229182533938

DemoData.java

package com.tangguanlin.easyexcel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
 * 说明:
 * 作者:汤观林
 * 日期:2021年12月29日 18时
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DemoData {

    private String name;

    private Date hirDate;

    private Double salary;
}

ReadExcel1.java

package com.tangguanlin.easyexcel;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
/**
 * 说明:最简单的读方式一
 * 作者:汤观林
 * 日期:2021年12月28日 21时
 */
public class ReadExcel1 {
    public static void main(String[] args) {

        String fileName = "user13.xlsx";

        EasyExcel.read(fileName,DemoData.class,new AnalysisEventListener<DemoData>(){

            //每解析一行Excel表格数据,就会调用一次
            @Override
            public void invoke(DemoData demoData, AnalysisContext analysisContext) {
               System.out.println("解析数据为:"+demoData);
            }

            //当全部解析完,被调用
            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                System.out.println("全部解析完");
            }
        }).sheet().doRead();
    }
}

运行结果:

解析数据为:DemoData{name='作文1', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=15.1}
解析数据为:DemoData{name='作文2', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=15.2}
解析数据为:DemoData{name='作文6', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=15.6}
解析数据为:DemoData{name='作文7', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=15.7}
全部解析完

3.2 最简单的读取Excel方式二

ReadExcel2.java

package com.tangguanlin.easyexcel;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.read.metadata.ReadSheet;
/**
 * 说明:最简单的读方式二
 * 作者:汤观林
 * 日期:2021年12月28日 21时
 */
public class ReadExcel2 {
    public static void main(String[] args) {

        String fileName = "user13.xlsx";

        //创建excelReader
        ExcelReader excelReader = EasyExcel.read(fileName, DemoData.class, new AnalysisEventListener<DemoData>() {

            //每解析一行Excel表格数据,就会调用一次
            @Override
            public void invoke(DemoData demoData, AnalysisContext analysisContext) {
                System.out.println("解析数据为:" + demoData);
            }

            //当全部解析完,被调用
            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                System.out.println("全部解析完");
            }
        }).build();

        //创建readSheet
        ReadSheet readSheet = EasyExcel.readSheet(0).build();
        //读
        excelReader.read(readSheet);

        //关闭流操作,在读取文件时创建临时文件,如果不关闭,磁盘会爆掉
        excelReader.finish();
    }
}

运行结果:

解析数据为:DemoData{name='作文1', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=15.1}
解析数据为:DemoData{name='作文2', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=15.2}
解析数据为:DemoData{name='作文6', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=15.6}
解析数据为:DemoData{name='作文7', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=15.7}
全部解析完

3.3 指定列名

user13.xlsx

image-20211229182533938

DemoData.java

package com.tangguanlin.easyexcel;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
 * 说明:
 * 作者:汤观林
 * 日期:2021年12月29日 18时
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DemoData {

    @ExcelProperty("日期标题")
    private Date hirDate;

    @ExcelProperty("字符串标题")
    private String name;

    @ExcelProperty("数字标题")
    private Double salary;

}

运行结果:

解析数据为:DemoData{name='作文1', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=15.1}
解析数据为:DemoData{name='作文2', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=15.2}
解析数据为:DemoData{name='作文6', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=15.6}
解析数据为:DemoData{name='作文7', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=15.7}
全部解析完

3.4 日期、数字格式化

user13.xlsx

image-20211229190724970

DemoData.java

package com.tangguanlin.easyexcel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.format.NumberFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
 * 说明:日期、数字格式化
 * 作者:汤观林
 * 日期:2021年12月29日 18时
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DemoData {

    @ExcelProperty("日期标题")
    @DateTimeFormat("yyyy年MM月dd日  hh时mm分ss秒")
    private Date hirDate;

    @ExcelProperty("字符串标题")
    private String name;

    @ExcelProperty("数字标题")
    @NumberFormat("#.##%")
    private String salary;
}

运行结果:

解析数据为:DemoData{name='作文1', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=1511.1%}
解析数据为:DemoData{name='作文2', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=1512.2%}
解析数据为:DemoData{name='作文6', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=1513.6%}
解析数据为:DemoData{name='作文7', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=1514.7%}
全部解析完

3.5 读取全部sheet数据

user13.xlsx

image-20211229192745156

image-20211229192803266

ReadExcel1.java

package com.tangguanlin.easyexcel;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
/**
 * 说明:读取全部sheet数据
 * 作者:汤观林
 * 日期:2021年12月28日 21时
 */
public class ReadExcel1 {
    public static void main(String[] args) {

        String fileName = "user13.xlsx";

        EasyExcel.read(fileName,DemoData.class,new AnalysisEventListener<DemoData>(){


            //每解析一行Excel表格数据,就会调用一次
            @Override
            public void invoke(DemoData demoData, AnalysisContext analysisContext) {
               System.out.println("解析数据为:"+demoData);
            }

            //当全部解析完,被调用
            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                System.out.println("全部解析完");
            }
        }).doReadAll();
    }
}

运行结果:

解析数据为:DemoData{name='作文11', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=1511.11%}
解析数据为:DemoData{name='作文21', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=1512.21%}
解析数据为:DemoData{name='作文61', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=1513.61%}
解析数据为:DemoData{name='作文71', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=1514.71%}
全部解析完
解析数据为:DemoData{name='作文12', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=1511.11%}
解析数据为:DemoData{name='作文22', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=1512.21%}
解析数据为:DemoData{name='作文62', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=1513.61%}
解析数据为:DemoData{name='作文72', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=1514.71%}
全部解析完
解析数据为:DemoData{name='作文13', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=1511.11%}
解析数据为:DemoData{name='作文23', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=1512.21%}
解析数据为:DemoData{name='作文63', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=1513.61%}
解析数据为:DemoData{name='作文73', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=1514.71%}
全部解析完

3.6 读取某几个sheet数据

ReadExcel3.java

package com.tangguanlin.easyexcel;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.read.builder.ExcelReaderBuilder;
import com.alibaba.excel.read.metadata.ReadSheet;
/**
 * 说明:读某几个sheet
 * 作者:汤观林
 * 日期:2021年12月28日 21时
 */
public class ReadExcel3 {
    public static void main(String[] args) {

        String fileName = "user13.xlsx";

        //创建excelReader
        ExcelReader excelReader = EasyExcel.read(fileName).build();

        //创建sheet0
        ReadSheet sheet0 = EasyExcel.readSheet(0).head(DemoData.class)
                                    .registerReadListener(new AnalysisEventListener<DemoData>(){

            @Override
            public void invoke(DemoData demoData, AnalysisContext analysisContext) {
                System.out.println("解析数据为:"+demoData);
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                System.out.println("sheet0解析完毕");
            }
        }).build();

        //创建sheet2
        ReadSheet sheet2 = EasyExcel.readSheet(2).head(DemoData.class)
                                    .registerReadListener(new AnalysisEventListener<DemoData>(){

            @Override
            public void invoke(DemoData demoData, AnalysisContext analysisContext) {
                System.out.println("解析数据为:"+demoData);
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                System.out.println("sheet2解析完毕");
            }
        }).build();

        //读
        excelReader.read(sheet0,sheet2);

        //释放资源
        excelReader.finish();
    }
}

运行结果:

解析数据为:DemoData{name='作文11', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=1511.11%}
解析数据为:DemoData{name='作文21', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=1512.21%}
解析数据为:DemoData{name='作文61', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=1513.61%}
解析数据为:DemoData{name='作文71', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=1514.71%}
sheet0解析完毕
解析数据为:DemoData{name='作文13', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=1511.11%}
解析数据为:DemoData{name='作文23', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=1512.21%}
解析数据为:DemoData{name='作文63', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=1513.61%}
解析数据为:DemoData{name='作文73', hirDate=Tue Dec 28 22:11:31 CST 2021, salary=1514.71%}
sheet2解析完毕

4 写入Excel

4.1 最简单的写方式一

User.java

package com.tangguanlin.easyexcel;
import com.alibaba.excel.annotation.ExcelProperty;
import java.util.Date;
/**
 * 说明:写入Excel方式一
 * 作者:汤观林
 * 日期:2021年12月28日 21时
 */
@Data
public class User {
    @ExcelProperty("用户编号")
    private  Integer userId;
    @ExcelProperty("姓名")
    private  String userName;
    @ExcelProperty("性别")
    private String gender;
    @ExcelProperty("工资")
    private Double salary;
    @ExcelProperty("入职时间")
    private Date hirDate;

    public User() {
    }

    public User(Integer userId, String userName, String gender, Double salary, Date hirDate) {
        this.userId = userId;
        this.userName = userName;
        this.gender = gender;
        this.salary = salary;
        this.hirDate = hirDate;
    }
  
}

WriteExcel1.java

package com.tangguanlin.easyexcel;
import com.alibaba.excel.EasyExcel;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
 * 说明:写入Excel方式一
 * 作者:汤观林
 * 日期:2021年12月28日 21时
 */
public class WriteExcel1 {
    public static void main(String[] args) {

        //创建一个Excel文档
        String fileName ="user1.xlsx";

        List<User> userList = new ArrayList<User>();
        User user1 = new User(1001,"李雷","男",1000.11,new Date());
        User user2 = new User(1002,"李雷","男",1000.11,new Date());
        User user3 = new User(1003,"李雷","男",1000.11,new Date());
        User user4 = new User(1004,"李雷","男",1000.11,new Date());

        userList.add(user1);
        userList.add(user2);
        userList.add(user3);
        userList.add(user4);

        EasyExcel.write(fileName,User.class).sheet("用户信息").doWrite(userList);
    }
}

运行结果:

image-20211228221744773

4.2 最简单的写方式二

WriteExcel2.java

package com.tangguanlin.easyexcel;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
 * 说明:写入Excel方式二
 * 作者:汤观林
 * 日期:2021年12月28日 22时
 */
public class WriteExcel2 {
    public static void main(String[] args) {

        //创建一个Excel文档
        String fileName ="user2.xlsx";

        List<User> userList = new ArrayList<User>();
        User user1 = new User(1001,"李雷","男",1000.11,new Date());
        User user2 = new User(1002,"李雷","男",1000.11,new Date());
        User user3 = new User(1003,"李雷","男",1000.11,new Date());
        User user4 = new User(1004,"李雷","男",1000.11,new Date());

        userList.add(user1);
        userList.add(user2);
        userList.add(user3);
        userList.add(user4);

        //创建ExcelWriter对象
        ExcelWriter excelWriter = EasyExcel.write(fileName, User.class).build();
        //创建sheet对象
        WriteSheet writeSheet = EasyExcel.writerSheet("用户信息").build();

        excelWriter.write(userList,writeSheet);

        //关闭资源
        excelWriter.finish();
    }
}

运行结果:

image-20211228222847356

4.3 排除某些字段

package com.tangguanlin.easyexcel;
import com.alibaba.excel.EasyExcel;
import java.util.*;
/**
 * 说明:排除某些字段
 * 作者:汤观林
 * 日期:2021年12月28日 22时
 */
public class WriteExcel3 {
    public static void main(String[] args) {
        //创建一个Excel文档
        String fileName ="user3.xlsx";

        List<User> userList = new ArrayList<User>();
        User user1 = new User(1001,"李雷","男",1000.11,new Date());
        User user2 = new User(1002,"李雷","男",1000.11,new Date());
        User user3 = new User(1003,"李雷","男",1000.11,new Date());
        User user4 = new User(1004,"李雷","男",1000.11,new Date());

        userList.add(user1);
        userList.add(user2);
        userList.add(user3);
        userList.add(user4);

        Set<String> set = new HashSet<>();
        set.add("hirDate");
        set.add("salary");

        EasyExcel.write(fileName,User.class).excludeColumnFiledNames(set).sheet("用户信息").doWrite(userList);
    }
}

运行结果:

image-20211228223725139

4.4 指定某几个字段

package com.tangguanlin.easyexcel;
import com.alibaba.excel.EasyExcel;
import java.util.*;
/**
 * 说明:指定某些字段
 * 作者:汤观林
 * 日期:2021年12月28日 22时
 */
public class WriteExcel4 {
    public static void main(String[] args) {

        //创建一个Excel文档
        String fileName ="user4.xlsx";

        List<User> userList = new ArrayList<User>();
        User user1 = new User(1001,"李雷","男",1000.11,new Date());
        User user2 = new User(1002,"李雷","男",1000.11,new Date());
        User user3 = new User(1003,"李雷","男",1000.11,new Date());
        User user4 = new User(1004,"李雷","男",1000.11,new Date());

        userList.add(user1);
        userList.add(user2);
        userList.add(user3);
        userList.add(user4);

        Set<String> set = new HashSet<>();
        set.add("userId");
        set.add("userName");
        set.add("salary");

        EasyExcel.write(fileName,User.class).includeColumnFiledNames(set).sheet("用户信息").doWrite(userList);
    }
}

运行结果:

image-20211228224228139

4.5 设置表格中列的顺序

将Java对象中指定的属性,插入到Excel表格中的指定的列(在Excel中进行排序)

@ExcelProperty(value="姓名",index = 1)  //index 排序
private  String userName;
package com.tangguanlin.easyexcel;
import com.alibaba.excel.annotation.ExcelProperty;
import java.util.Date;
/**
 * 说明:设置表格中列的顺序
 * 作者:汤观林
 * 日期:2021年12月28日 21时
 */
public class User {
    @ExcelProperty(value="用户编号",index = 0)
    private  Integer userId;
    @ExcelProperty(value="姓名",index = 1)
    private  String userName;
    @ExcelProperty(value="性别",index = 2)
    private String gender;
    @ExcelProperty(value="工资",index = 4)
    private Double salary;
    @ExcelProperty(value="入职时间",index = 3)
    private Date hirDate;

    public User() {
    }

    public User(Integer userId, String userName, String gender, Double salary, Date hirDate) {
        this.userId = userId;
        this.userName = userName;
        this.gender = gender;
        this.salary = salary;
        this.hirDate = hirDate;
    }
}

运行结果:

image-20211228224957533

4.6 复杂头数据写入

CompleHeadUser.java

package com.tangguanlin.easyexcel;
import com.alibaba.excel.annotation.ExcelProperty;
import java.util.Date;
/**
 * 说明:复杂头对象
 * 作者:汤观林
 * 日期:2021年12月28日 22时
 */
public class CompleHeadUser {

    @ExcelProperty({"用户主题1","用户编号"})
    private Integer userId;
    @ExcelProperty({"用户主题1","用户名称"})
    private String userName;
    @ExcelProperty({"用户主题3","入职时间"})
    private Date hireDate;

    public CompleHeadUser() {
    }

    public CompleHeadUser(Integer userId, String userName, Date hireDate) {
        this.userId = userId;
        this.userName = userName;
        this.hireDate = hireDate;
    }
}

运行结果:

image-20211228230850930

4.7 多次写到Excel的同一个sheet中

package com.tangguanlin.easyexcel;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
 * 说明:多次写到Excel的同一个sheet中
 * 作者:汤观林
 * 日期:2021年12月28日 23时
 */
public class WriteExcel7 {
    public static void main(String[] args) {
        //创建一个Excel文档
        String fileName ="user7.xlsx";

        List<User> userList = new ArrayList<User>();
        User user1 = new User(1001,"李雷","男",1000.11,new Date());
        User user2 = new User(1002,"李雷","男",1000.11,new Date());
        User user3 = new User(1003,"李雷","男",1000.11,new Date());
        User user4 = new User(1004,"李雷","男",1000.11,new Date());

        userList.add(user1);
        userList.add(user2);
        userList.add(user3);
        userList.add(user4);

        //创建excelWriter
        ExcelWriter excelWriter = EasyExcel.write(fileName, User.class).build();
        //创建writeSheet
        WriteSheet writeSheet = EasyExcel.writerSheet("用户信息06").build();
        for(int i=0;i<5;i++){
            excelWriter.write(userList,writeSheet);
        }
        excelWriter.finish();
    }
}

运行结果:

image-20211228232158366

4.8 多次写到Excel的不同sheet中

package com.tangguanlin.easyexcel;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
 * 说明:多次写到Excel的b不同sheet中
 * 作者:汤观林
 * 日期:2021年12月28日 23时
 */
public class WriteExcel8 {
    public static void main(String[] args) {
        //创建一个Excel文档
        String fileName ="user8.xlsx";

        List<User> userList = new ArrayList<User>();
        User user1 = new User(1001,"李雷","男",1000.11,new Date());
        User user2 = new User(1002,"李雷","男",1000.11,new Date());
        User user3 = new User(1003,"李雷","男",1000.11,new Date());
        User user4 = new User(1004,"李雷","男",1000.11,new Date());

        userList.add(user1);
        userList.add(user2);
        userList.add(user3);
        userList.add(user4);

        //创建excelWriter
        ExcelWriter excelWriter = EasyExcel.write(fileName, User.class).build();

        for(int i=0;i<5;i++){
            //创建writeSheet
            WriteSheet writeSheet = EasyExcel.writerSheet("用户信息"+i).build();
            excelWriter.write(userList,writeSheet);
        }
        excelWriter.finish();
    }
}

运行结果:

image-20211228232706554

4.9 日期、数字格式化

package com.tangguanlin.easyexcel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.format.NumberFormat;
import java.util.Date;
/**
 * 说明:日期、数字类型格式化
 * 作者:汤观林
 * 日期:2021年12月28日 21时
 */
public class User {
    
    @ExcelProperty(value="用户编号",index = 0)
    private  Integer userId;
    
    @ExcelProperty(value="姓名",index = 1)
    private  String userName;
    
    @ExcelProperty(value="性别",index = 2)
    private String gender;
    
    @NumberFormat("#.#")       //数字格式化
    @ExcelProperty(value="工资",index = 4)
    private Double salary;
    
    @DateTimeFormat("yyyy年MM月dd日")    //日期格式化
    @ExcelProperty(value="入职时间",index = 3)
    private Date hirDate;

    public User() {
    }

    public User(Integer userId, String userName, String gender, Double salary, Date hirDate) {
        this.userId = userId;
        this.userName = userName;
        this.gender = gender;
        this.salary = salary;
        this.hirDate = hirDate;
    }
}

运行结果:

image-20211229003154351

4.10 写入图片到Excel

5种方式:

        ImageData.java                              WriteExcel10.java
            
//方式一:使用抽象文件表示一个图片
private File file;                   	 imageData.setFile(new File("image.jpg"));

//方式二:使用输入流保存一个图片
private InputStream inputStream;     	 imageData.setInputStream(new FileInputStream("image.jpg"));

//方式三:当使用String类型保存一个图片的时候需要使用StringImageConverter转换器
@ExcelProperty(converter = StringImageConverter.class)
private  String string;               	 imageData.setString("image.jpg");

//方式四:使用二进制数据保存为一个图片
private  byte[] byteArray;               int length = (int)new File("image.jpg").length();
 										 byte[] b = new byte[length];
        								 FileInputStream fis = new FileInputStream("image.jpg");
        								 fis.read(b,0,length);
        								 imageData.setByteArray(b);

//方式五:使用网络连接保存一个图片
private URL url;          				 imageData.setUrl(new URL("www.baidu.com"));

ImageData.java

package com.tangguanlin.easyexcel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.converters.string.StringImageConverter;
import lombok.Data;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.Arrays;
/**
 * 说明:写入图片的5种方式
 * 作者:汤观林
 * 日期:2021年12月29日 15时
 */
@Data
public class ImageData {

    private File file;  //方式一:使用抽象文件表示一个图片

    private InputStream inputStream; //方式二:使用输入流保存一个图片

    @ExcelProperty(converter = StringImageConverter.class)
    private  String string; //方式三:当使用String类型保存一个图片的时候需要使用StringImageConverter转换器

    private  byte[] byteArray; //方式四:使用二进制数据保存为一个图片

    private URL url; //方式五:使用网络连接保存一个图片

    public ImageData() {
    }
}

WriteExcel10.java

package com.tangguanlin.easyexcel;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import java.io.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
/**
 * 说明:将图片写入到Excel的5种方式
 * 作者:汤观林
 * 日期:2021年12月28日 23时
 */
public class WriteExcel10 {
    public static void main(String[] args) throws IOException {
        //创建一个Excel文档
        String fileName ="user10.xlsx";

        List<ImageData>  imageList = new ArrayList<ImageData>();
        ImageData imageData = new ImageData();

        //方式一:使用抽象文件表示一个图片
        imageData.setFile(new File("image.jpg"));

        //方式二:使用输入流保存一个图片
        imageData.setInputStream(new FileInputStream("image.jpg"));

        //方式三:当使用String类型保存一个图片的时候需要使用StringImageConverter转换器
        imageData.setString("image.jpg");

        //方式四:使用二进制数据保存为一个图片
        byte[] b = new byte[(int)new File("image.jpg").length()];
        FileInputStream fis = new FileInputStream("image.jpg");
        fis.read(b,0,(int)new File("image.jpg").length());
        imageData.setByteArray(b);

        //方式五:使用网络连接保存一个图片
        imageData.setUrl(new URL("https://gitee.com/tangguanlin2006/image/raw/master/20211228212606.png"));

        imageList.add(imageData);

        //创建excelWriter
        ExcelWriter excelWriter = EasyExcel.write(fileName, ImageData.class).build();
        //创建writeSheet
        WriteSheet writeSheet = EasyExcel.writerSheet("用户信息").build();
        excelWriter.write(imageList,writeSheet);

        excelWriter.finish();
    }
}

运行结果:

image-20211229160826550

4.11 设置Excel列宽行高

属性:

//修饰类
@HeadRowHeight(40)  //设置标题高度
@ColumnWidth(30)   //设置列宽
@ContentRowHeight(50) //设置内容高度
public class ImageData {
    
}
    
//修饰属性
@ColumnWidth(30) //设置列宽
private File file;

ImageData.java

package com.tangguanlin.easyexcel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import com.alibaba.excel.converters.string.StringImageConverter;
import lombok.Data;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.Arrays;
/**
 * 说明:设置列宽行高
 * 作者:汤观林
 * 日期:2021年12月29日 15时
 */
@Data
@HeadRowHeight(40)  //设置标题高度
@ColumnWidth(30) //设置列宽
@ContentRowHeight(50) //设置内容高度
public class ImageData {

    private File file;  //方式一:使用抽象文件表示一个图片

    private InputStream inputStream; //方式二:使用输入流保存一个图片

    @ExcelProperty(converter = StringImageConverter.class)
    private  String string; //方式三:当使用String类型保存一个图片的时候需要使用StringImageConverter转换器

    private  byte[] byteArray; //方式四:使用二进制数据保存为一个图片

    private URL url; //方式五:使用网络连接保存一个图片

    public ImageData() {
    }
}

运行结果:

image-20211229162220445

4.12 设置样式

//修饰类  或  字段

//头背景设置成红色 IndexedColors.PINK.getIndex() 10:红色
@HeadStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND,fillForegroundColor = 10)

//头字体设置成20
@HeadFontStyle(fontHeightInPoints = 20)

//内容的背景设置成绿色 IndexedColors.PINK.getIndex()  17:绿色
@ContentStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND,fillForegroundColor = 17 )

//内容字体设置成20
@ContentFontStyle(fontHeightInPoints = 20)

DemoStyleData.java

package com.tangguanlin.easyexcel;
import cn.hutool.db.DaoTemplate;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ContentFontStyle;
import com.alibaba.excel.annotation.write.style.ContentStyle;
import com.alibaba.excel.annotation.write.style.HeadFontStyle;
import com.alibaba.excel.annotation.write.style.HeadStyle;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.IndexedColors;
import java.util.Date;
/**
 * 说明: 设置样式
 * 作者:汤观林
 * 日期:2021年12月29日 16时
 */
@Data
@AllArgsConstructor
//头背景设置成红色 IndexedColors.PINK.getIndex() 10:红色
@HeadStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND,fillForegroundColor = 10)
//头字体设置成20
@HeadFontStyle(fontHeightInPoints = 20)
//内容的背景设置成绿色 IndexedColors.PINK.getIndex()  17:绿色
@ContentStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND,fillForegroundColor = 17 )
//内容字体设置成20
@ContentFontStyle(fontHeightInPoints = 20)
public class DemoStyleData {

    @ExcelProperty("字符串标题")
    private String string;

    @ExcelProperty("日期标题")
    private Date Date;

    @ExcelProperty("数字标题")
    private Double doubleData;
}

运行结果:

image-20211229171616784

4.13 合并单元格

//修饰类
//合并单元格   		 (起始行,结束行,起始列,结束列)
@OnceAbsoluteMerge(firstRowIndex = 3,lastRowIndex = 5,firstColumnIndex = 1,lastColumnIndex = 2)
public class DemoMergeData {

}

//修饰列
//每隔2行合并一次(竖着合并单元格)  
@ContentLoopMerge(eachRow = 2)
@ExcelProperty("字符串标题")
private String string;

WriteExcel12.java

package com.tangguanlin.easyexcel;
import com.alibaba.excel.EasyExcel;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
 * 说明:合并单元格
 * 作者:汤观林
 * 日期:2021年12月28日 23时
 */
public class WriteExcel12 {
    public static void main(String[] args) {
        //创建一个Excel文档
        String fileName ="user12.xlsx";

        List<DemoMergeData> mergeDataList = new ArrayList<DemoMergeData>();
        DemoMergeData mergeData1 = new DemoMergeData("作文1",new Date(),15.1);
        DemoMergeData mergeData2 = new DemoMergeData("作文2",new Date(),15.2);
        DemoMergeData mergeData3 = new DemoMergeData("作文3",new Date(),15.3);
        DemoMergeData mergeData4 = new DemoMergeData("作文4",new Date(),15.4);
        DemoMergeData mergeData5 = new DemoMergeData("作文5",new Date(),15.5);
        DemoMergeData mergeData6 = new DemoMergeData("作文6",new Date(),15.6);
        DemoMergeData mergeData7 = new DemoMergeData("作文7",new Date(),15.7);

        mergeDataList.add(mergeData1);
        mergeDataList.add(mergeData2);
        mergeDataList.add(mergeData3);
        mergeDataList.add(mergeData4);
        mergeDataList.add(mergeData5);
        mergeDataList.add(mergeData6);
        mergeDataList.add(mergeData7);

        EasyExcel.write(fileName, DemoMergeData.class).sheet("合并单元格").doWrite(mergeDataList);
    }
}

运行结果:

image-20211229174608985

4.14 字段填充

​ 填充单个属性使用{}作为占位符,在大括号里面定义属性名称,

如果{}想不作为占位符,可以已使用反斜杠进行转义。

template.xlsx 填充模板

姓名工资复杂忽略
{name}{number}{name}今年{number}岁了\ {name \ } 忽略,{name}

FillData.java

package com.tangguanlin.easyexcel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
 * 说明:填充数据
 * 作者:汤观林
 * 日期:2021年12月29日 21时
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class FillData {

    private String name;
    private double number;
}

WriteExcel13.java

package com.tangguanlin.easyexcel;
import com.alibaba.excel.EasyExcel;
/**
 * 说明:字段填充
 * 作者:汤观林
 * 日期:2021年12月29日 21时
 */
public class WriteExcel13 {
    public static void main(String[] args) {

        //根据哪个模板进行填充
        String templateName = "template.xlsx";

        //填充完成之后的Excel
        String fullName = "fullFile.xlsx";

        FillData fillData = new FillData();
        fillData.setName("小明");
        fillData.setNumber(1000.12);

        //进行填充
        EasyExcel.write(fullName).withTemplate(templateName).sheet().doFill(fillData);
    }
}

运行结果:

fullFile.xlsx

image-20211229214718697

4.15 列表填充

templateList.xlsx 填充模板

姓名工资
{==.==name}{==.==number}

WriteExcel13.java

package com.tangguanlin.easyexcel;
import com.alibaba.excel.EasyExcel;
import java.util.ArrayList;
import java.util.List;
/**
 * 说明:字段填充
 * 作者:汤观林
 * 日期:2021年12月29日 21时
 */
public class WriteExcel13 {
    public static void main(String[] args) {

        //根据哪个模板进行填充
        String templateName = "templateList.xlsx";

        //填充完成之后的Excel
        String fullName = "fullFileList.xlsx";

        List<FillData> fillDataList = new ArrayList<>();
        FillData fillData1 = new FillData("小明1",1000.12);
        FillData fillData2 = new FillData("小明2",1000.12);
        FillData fillData3 = new FillData("小明3",1000.12);
        FillData fillData4 = new FillData("小明4",1000.12);
        FillData fillData5 = new FillData("小明5",1000.12);
        FillData fillData6 = new FillData("小明6",1000.12);
        FillData fillData7 = new FillData("小明7",1000.12);
        fillDataList.add(fillData1);
        fillDataList.add(fillData2);
        fillDataList.add(fillData3);
        fillDataList.add(fillData4);
        fillDataList.add(fillData5);
        fillDataList.add(fillData6);
        fillDataList.add(fillData7);

        //进行填充
        EasyExcel.write(fullName).withTemplate(templateName).sheet().doFill(fillDataList);
    }
}

运行结果:

fullFileList.xlsx

image-20211229220009670

5 web操作

5.1 Excel文件上传

(省略)

5.2 Excel文件下载

(省略)

### 关于黑马程序员 EasyExcel学习笔记与教程 #### 易用性介绍 Apache POI 是处理 Excel 文件的传统方式之一,但它存在内存占用高的问题。相比之下,阿里巴巴开源的 **EasyExcel** 提供了一种轻量级解决方案,专注于解决大文件读写的性能瓶颈[^1]。 #### 基本功能概述 EasyExcel 支持两种主要操作模式: - **读取数据**:通过定义实体类并配置解析器来高效读取大规模 Excel 数据。 - **写入数据**:支持自动生成复杂的表格结构,并允许动态调整样式和内容。 以下是基于 EasyExcel 实现的一个简单示例: ```java import com.alibaba.excel.EasyExcel; import java.util.ArrayList; import java.util.List; public class EasyExcelDemo { public static void main(String[] args) { String fileName = "example.xlsx"; // 写入数据 List<UserData> data = new ArrayList<>(); data.add(new UserData("Alice", 25)); data.add(new UserData("Bob", 30)); EasyExcel.write(fileName, UserData.class).sheet("Sheet1").doWrite(data); // 读取数据 EasyExcel.read(fileName, UserData.class, new PageReadListener<>(dataList -> { dataList.forEach(System.out::println); })).sheet().doRead(); } } class UserData { private String name; private int age; public UserData() {} public UserData(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "UserData{name='" + name + "', age=" + age + "}"; } // Getters and Setters omitted for brevity. } ``` 此代码展示了如何利用 `EasyExcel` 进行基本的数据读写操作[^2]。 #### 高级特性说明 除了基础的功能外,EasyExcel 还提供了许多高级选项: - 自定义单元格样式(字体、颜色等)。 - 处理复杂表头或多层嵌套表头。 - 支持监听器机制,在读取过程中实时处理每一行数据。 这些特性的实现通常依赖于扩展接口或继承默认行为来进行定制化开发。 --- ####
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值