EasyExcel简单入门

1.导入依赖

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>3.0.5</version>
        </dependency>

2.读excel

2.1excel表

姓名

年龄

创建时间

张三

20

2021-05-05 07:05:55

李四

15

2019-10-05 10:17:42

王五

22

2022-11-15 16:20:23

2.2使用一个对象接收Excel里的数据

@Getter
@Setter
@EqualsAndHashCode
public class ExcelData {
    /**
     * 强制读取第0个 这里不建议 index 和 name 同时用,要么一个对象只用index,要么一个对象只用name去匹配
     */
    @ExcelProperty(index = 0)
    private String name;
    /**
     * 用名字去匹配,这里需要注意,如果名字重复,会导致只有一个字段读取到数据
     */
    @ExcelProperty("年龄")
    private Integer age;
    @ExcelProperty("创建时间")
    private Date date;
}

2.3创建一个监听器来实现读取数据

// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
@Slf4j
public class DemoDataListener implements ReadListener<ExcelData> {
​
    /**
     * 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 100;
    /**
     * 缓存的数据
     */
    private List<ExcelData> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
    /**
     * 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
     */
    private DemoDAO demoDAO;
​
    public DemoDataListener() {
        // 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数
        demoDAO = new DemoDAO();
    }
​
    /**
     * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
     *
     * @param demoDAO
     */
    public DemoDataListener(DemoDAO demoDAO) {
        this.demoDAO = demoDAO;
    }
​
    /**
     * 这个每一条数据解析都会来调用
     *
     * @param data    one row value. Is is same as {@link AnalysisContext#readRowHolder()}
     * @param context
     */
    @Override
    public void invoke(DemoData data, AnalysisContext context) {
        log.info("解析到一条数据:{}", JSON.toJSONString(data));
        cachedDataList.add(data);
        // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
        if (cachedDataList.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        }
    }
​
    /**
     * 所有数据解析完成了 都会来调用
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        saveData();
        log.info("所有数据解析完成!");
    }
​
    /**
     * 加上存储数据库
     */
    private void saveData() {
        log.info("{}条数据,开始存储数据库!", cachedDataList.size());
        demoDAO.save(cache
        
        
        dDataList);
        log.info("存储数据库成功!");
    }
}
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:\\信息.xls"
            head            每行数据对应的实体;Student.class
            readListener    读监听器,每读一样就会调用一次该监听器的invoke方法
        
            sheet方法参数: 工作表的顺序号(从0开始)或者工作表的名字,不传默认为0
        */
        // 封装工作簿对象
        ExcelReaderBuilder workBook = EasyExcel.read
                ("d:\\信息.xls", Student.class, new DemoDataListener());
​
        // 封装工作表
        ExcelReaderSheetBuilder sheet1 = workBook.sheet();
        // 读取
        sheet1.doRead();
    }
}

2.3写excel

   /**
     * 最简单的写
     * <p>
     * 1. 创建excel对应的实体对象 参照{@link ExcelData}
     * <p>
     * 2. 直接写即可
     */
    @Test
    public void simpleWrite() {
        // 注意 simpleWrite在数据量不大的情况下可以使用(5000以内,具体也要看实际情况),数据量大参照 重复多次写入
        
        // 写法1 JDK8+
        // since: 3.0.0-beta1
        String fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";
        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        // 如果这里想
        
        03 则 传入excelType参数即可
        EasyExcel.write(fileName, ExcelData.class)
            .sheet("模板")
            .doWrite(() -> {
                // 分页查询数据
                return data();
            });
​
        // 写法2
        fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";
        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        // 如果这里想使用03 则 传入excelType参数即可
        EasyExcel.write(fileName, ExcelData.class).sheet("模板").doWrite(data());
​
        // 写法3
        fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";
        // 这里 需要指定写用哪个class去写
        ExcelWriter excelWriter = null;
        try {
            excelWriter = EasyExcel.write(fileName, ExcelData.class).build();
            WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
            excelWriter.write(data(), writeSheet);
        } finally {
            // 千万别忘记finish 会帮忙关闭流
            if (excelWriter != null) {
                excelWriter.finish();
            }
        }
    }

3.1excel文件上传

@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.2excel文件下载

编写实体类

@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常用参数API

关于常见类解析

  • EasyExcel 入口类,用于构建开始各种操作
  • ExcelReaderBuilder ExcelWriterBuilder 构建出一个 ReadWorkbook WriteWorkbook,可以理解成一个excel对象,一个excel只要构建一个
  • ExcelReaderSheetBuilder ExcelWriterSheetBuilder 构建出一个 ReadSheet WriteSheet对象,可以理解成excel里面的一页,每一页都要构建一个
  • ReadListener 在每一行读取完毕后都会调用ReadListener来处理数据
  • WriteHandler 在每一个操作包括创建单元格、创建表格等都会调用WriteHandler来处理数据
  • 所有配置都是继承的,Workbook的配置会被Sheet继承,所以在用EasyExcel设置参数的时候,在EasyExcel...sheet()方法之前作用域是整个sheet,之后针对单个sheet

注解

  • ExcelProperty

指定当前字段对应excel中的那一列。可以根据名字或者Index去匹配。当然也可以不写,默认第一个字段就是index=0,以此类推。千万注意,要么全部不写,要么全部用index,要么全部用名字去匹配。千万别三个混着用,除非你非常了解源代码中三个混着用怎么去排序的。

  • ExcelIgnore

默认所有字段都会和excel去匹配,加了这个注解会忽略该字段

  • DateTimeFormat

日期转换,用String去接收excel日期格式的数据会调用这个注解。里面的value参照java.text.SimpleDateFormat

  • NumberFormat

数字转换,用String去接收excel数字格式的数据会调用这个注解。里面的value参照java.text.DecimalFormat

  • ExcelIgnoreUnannotated

默认不加ExcelProperty 的注解的都会参与读写,加了不会参与

参数

通用参数

ReadWorkbook,ReadSheet 都会有的参数,如果为空,默认使用上级。

  • converter

转换器,默认加载了很多转换器。也可以自定义。

  • readListener

监听器,在读取数据的过程中会不断的调用监听器。

  • headRowNumber

需要读的表格有几行头数据。默认有一行头,也就是认为第二行开始起为数据。

  • head

 与clazz二选一。读取文件头对应的列表,会根据列表匹配数据,建议使用class。

  • clazz

与head二选一。读取文件的头对应的class,也可以使用注解。如果两个都不指定,则会读取全部数据。

  • autoTrim

字符串、表头等数据自动trim

  • password

读的时候是否需要使用密码

6.2.2.2ReadWorkbook(理解成excel对象)参数

  • excelType

当前excel的类型 默认会自动判断

  • inputStream

与file二选一。读取文件的流,如果接收到的是流就只用,不用流建议使用file参数。因为使用了inputStream easyexcel会帮忙创建临时文件,最终还是file

  • file

与inputStream二选一。读取文件的文件。

  • autoCloseStream

自动关闭流。

  • readCache

默认小于5M用 内存,超过5M会使用 EhCache,这里不建议使用这个参数。

  • useDefaultListener

@since 2.1.4 默认会加入ModelBuildEventListener 来帮忙转换成传入class的对象,设置成false后将不会协助转换对象,自定义的监听器会接收到Map对象,如果还想继续接听到class对象,请调用readListener方法,加入自定义的beforeListener、 ModelBuildEventListener、 自定义的afterListener即可。

ReadSheet(就是excel的一个Sheet)参数

  • sheetNo

需要读取Sheet的编码,建议使用这个来指定读取哪个Sheet

  • sheetName

根据名字去匹配Sheet,excel 2003不支持根据名字去匹配

注解

  • ExcelProperty

index 指定写到第几列,默认根据成员变量排序。value指定写入的名称,默认成员变量的名字,多个value可以参照快速开始中的复杂头

  • ExcelIgnore

默认所有字段都会写入excel,这个注解会忽略这个字段

  • DateTimeFormat

日期转换,将Date写到excel会调用这个注解。里面的value参照java.text.SimpleDateFormat

  • NumberFormat

数字转换,用Number写excel会调用这个注解。里面的value参照java.text.DecimalFormat

  • ExcelIgnoreUnannotated

默认不加ExcelProperty 的注解的都会参与读写,加了不会参与

参数

通用参数

WriteWorkbook,WriteSheet ,WriteTable都会有的参数,如果为空,默认使用上级。

  • converter

转换器,默认加载了很多转换器。也可以自定义。

  • writeHandler

写的处理器。可以实现WorkbookWriteHandler,SheetWriteHandler,RowWriteHandler,CellWriteHandler,在写入excel的不同阶段会调用

  • relativeHeadRowIndex

距离多少行后开始。也就是开头空几行

  • needHead

是否导出头

  • head

 与clazz二选一。写入文件的头列表,建议使用class。

  • clazz

与head二选一。写入文件的头对应的class,也可以使用注解。

  • autoTrim

字符串、表头等数据自动trim

WriteWorkbook(理解成excel对象)参数

  • excelType

当前excel的类型 默认xlsx

  • outputStream

与file二选一。写入文件的流

  • file

与outputStream二选一。写入的文件

  • templateInputStream

模板的文件流

  • templateFile

模板文件

  • autoCloseStream

自动关闭流。

  • password

写的时候是否需要使用密码

  • useDefaultStyle

写的时候是否是使用默认头

6.3.2.3WriteSheet(就是excel的一个Sheet)参数

  • sheetNo

需要写入的编码。默认0

  • sheetName

需要些的Sheet名称,默认同sheetNo

WriteTable(就把excel的一个Sheet,一块区域看一个table)参数

  • tableNo

需要写入的编码。默认0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
EasyExcel 是一个基于阿里巴巴的开源项目 easyexcel 开发的 Excel 工具类库,可以方便快捷地读取、写入 Excel 文件。它支持大批量数据的导入导出,可以读取 Excel 中的复杂表格,并且能够将 Java 对象映射到 Excel 单元格中。 在 EasyExcel 中,图片的导入和导出可以通过一个 POJO 类来实现。下面是一个示例: ```java public class ImageData { //图片文件名 private String fileName; //图片字节数组 private byte[] imageBytes; public String getFileName() { return fileName; } public void setFileName(String fileName) { this.fileName = fileName; } public byte[] getImageBytes() { return imageBytes; } public void setImageBytes(byte[] imageBytes) { this.imageBytes = imageBytes; } } ``` 这个 POJO 类包含了图片文件名和图片字节数组两个属性,分别用于表示图片的文件名和内容。在导入和导出 Excel 文件时,我们可以使用 EasyExcel 提供的注解来指定这个 POJO 类中的属性和 Excel 表格中的列之间的映射关系。 下面是一个示例,演示了如何将 POJO 类中的图片数据导出到 Excel 文件中: ```java public static void writeExcel() throws IOException { //定义 Excel 文件输出流 OutputStream outputStream = new FileOutputStream("test.xlsx"); //创建 EasyExcel 写入器 ExcelWriter excelWriter = EasyExcel.write(outputStream, ImageData.class).build(); //创建一个 Sheet WriteSheet writeSheet = EasyExcel.writerSheet("Sheet1").build(); //创建一个图片 BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB); Graphics2D g = image.createGraphics(); g.setColor(Color.WHITE); g.fillRect(0, 0, 100, 100); g.setColor(Color.BLACK); g.drawString("Hello, EasyExcel", 10, 50); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ImageIO.write(image, "png", outputStream); byte[] bytes = outputStream.toByteArray(); //创建一个 ImageData 对象 ImageData imageData = new ImageData(); imageData.setFileName("test.png"); imageData.setImageBytes(bytes); //将 ImageData 对象写入到 Excel 文件中 excelWriter.write(Arrays.asList(imageData), writeSheet); //关闭 Excel 写入器 excelWriter.finish(); } ``` 在这个示例中,我们首先创建了一个 BufferedImage 对象,然后使用 Graphics2D 绘制了一个字符串,并将其转换为了字节数组。接着,我们创建了一个 ImageData 对象,并将图片文件名和字节数组分别设置到了对象的属性中。最后,我们将 ImageData 对象写入到了 Excel 文件中。 导入 Excel 文件中包含图片数据的过程与导出类似,只需要使用 EasyExcel 提供的读取器和监听器,读取 Excel 文件中的数据,并将读取到的数据转换为 POJO 对象即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值