手拉手浅学Springboot+EasyExcel

环境介绍

技术栈

springboot+mybatis-plus+mysql+easyexcel

软件

版本

mysql

8

IDEA

IntelliJ IDEA 2022.2.1

JDK

1.8

Spring Boot

2.7.13

mybatis-plus

3.5.3.2

EasyExcel是一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具。

他能让你在不用考虑性能、内存的等因素的情况下,快速完成Excel的读、写等功能。

官网https://easyexcel.opensource.alibaba.com/

加入依赖

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

读Excel

  • 编写实体类

@TableName(value ="product")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Product implements Serializable {
    /**
     * 序号
     */
    @TableId(type = IdType.AUTO)
    @ExcelProperty("序号")
    private Integer number;

    /**
     * 创建时间
     */
    @ExcelProperty("创建时间")
    private Date createtime;

    /**
     * 产品名称
     */
    @ExcelProperty("产品名称")
    private String productname;

    /**
     * 产品编号
     */
    @ExcelProperty("产品编号")
    private String productnumber;

    /**
     * 产品型号
     */
    @ExcelProperty("产品型号")
    private String manufacturer;

    /**
     * 产品位置
     */
    @ExcelProperty("产品位置")
    private String producepath;

    /**
     * 图片位置
     */
    @ExcelProperty("图片位置")
    private String imagepath;

    /**
     * 使用单位
     */
    @ExcelProperty("使用单位")
    private String unit;

    /**
     * 金额
     */
    @ExcelProperty("金额")
    private Integer money;

    /**
     * 入库时间
     */
    @ExcelProperty("入库时间")
    private Date intime;

    /**
     * 出库时间
     */
    @ExcelProperty("出库时间")
    private Date puttime;

    /**
     * 操作人
     */
    @ExcelProperty("操作人")
    private String operator;

    /**
     * 创建人
     */
    @ExcelProperty("创建人")
    private String createduser;

    /**
     * 备注
     */
    @ExcelProperty("备注")
    private String notes;

    /**
     * 产品数量
     */
    @ExcelProperty("产品数量")
    private Integer producedigit;

    /**
     * 产品单位
     */
    @ExcelProperty("产品单位")
    private String productunit;

    @TableField(exist = false)
    private static final long serialVersionUID = 1L;
}

  • 监听器

使用官方默认提供的监听器

  • 调用API
@Test
public void simpleRead() {
    //String fileName = TestFileUtil.getPath() + "simpleWriteTest1702391756908.xlsx";
    String fileName = "C:\\Users\\1111\\Desktop\\simpleWriteTest1702391756908.xlsx";
    // 这里默认每次会读取100条数据 然后返回过来 直接调用使用数据就行
    // 具体需要返回多少行可以在`PageReadListener`的构造函数设置
    EasyExcel.read(fileName, Product.class, new PageReadListener<Product>(dataList -> {
        for (Product product : dataList) {
            System.out.println(product);
            //log.info("读取到一条数据{}", JSON.toJSONString(product));
        }
    })).sheet().doRead();
}

写Excel

TestFileUtil工具类

public class TestFileUtil {
    public static InputStream getResourcesFileInputStream(String fileName) {
        return Thread.currentThread().getContextClassLoader().getResourceAsStream("" + fileName);
    }

    public static String getPath() {
        return TestFileUtil.class.getResource("/").getPath();
    }

    public static TestPathBuild pathBuild() {
        return new TestPathBuild();
    }

    public static File createNewFile(String pathName) {
        File file = new File(getPath() + pathName);
        if (file.exists()) {
            file.delete();
        } else {
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
        }
        return file;
    }

    public static File readFile(String pathName) {
        return new File(getPath() + pathName);
    }

    public static File readUserHomeFile(String pathName) {
        return new File(System.getProperty("user.home") + File.separator + pathName);
    }

    /**
     * build to test file path
     **/
    public static class TestPathBuild {
        private TestPathBuild() {
            subPath = new ArrayList<>();
        }

        private final List<String> subPath;

        public TestPathBuild sub(String dirOrFile) {
            subPath.add(dirOrFile);
            return this;
        }

        public String getPath() {
            if (CollectionUtils.isEmpty(subPath)) {
                return TestFileUtil.class.getResource("/").getPath();
            }
            if (subPath.size() == 1) {
                return TestFileUtil.class.getResource("/").getPath() + subPath.get(0);
            }
            StringBuilder path = new StringBuilder(TestFileUtil.class.getResource("/").getPath());
            path.append(subPath.get(0));
            for (int i = 1; i < subPath.size(); i++) {
                path.append(File.separator).append(subPath.get(i));
            }
            return path.toString();
        }

    }
}

#

  • 实体类编写
@TableName(value ="product")

@Data

@NoArgsConstructor

@AllArgsConstructor

public class Product implements Serializable {

    /**

     * 序号_自动生成

     */

    @TableId(type = IdType.AUTO)

    @ExcelProperty("序号")

    private Integer number;
    /**

     * 创建时间

     */

    @ExcelProperty("创建时间")

    private Date createtime;
    /**

     * 产品名称

     */

    @ExcelProperty("产品名称")

    private String productname;
    /**

     * 产品编号

     */

    @ExcelProperty("产品编号")

    private String productnumber;
    /**

     * 产品型号

     */

    @ExcelProperty("产品型号")

    private String manufacturer;
    /**

     * 产品位置

     */

    @ExcelProperty("产品位置")

    private String producepath;
    /**

     * 图片位置

     */

    @ExcelProperty("图片位置")

    private String imagepath;
    /**

     * 使用单位

     */

    @ExcelProperty("使用单位")

    private String unit;
    /**

     * 金额

     */

    @ExcelProperty("金额")

    private Integer money;
    /**

     * 入库时间

     */

    @ExcelProperty("入库时间")

    private Date intime;
    /**

     * 出库时间

     */

    @ExcelProperty("出库时间")

    private Date puttime;
    /**

     * 操作人

     */

    @ExcelProperty("操作人")

    private String operator;
    /**

     * 创建人

     */

    @ExcelProperty("创建人")

    private String createduser;
    /**

     * 备注

     */

    @ExcelProperty("备注")

    private String notes;
    /**

     * 产品数量

     */

    @ExcelProperty("产品数量")

    private Integer producedigit;
    /**

     * 产品单位

     */

    @ExcelProperty("产品单位")

    private String productunit;
    @TableField(exist = false)

    private static final long serialVersionUID = 1L;

}

  • 数据生成方法
private List<Product> getData(int count) {

    List<Product> list = ListUtils.newArrayList();

    for (int i = 0; i < count; i++) {
        Product product = new Product();
        product.setCreatetime(new Date());
        product.setProductname("服务器00"+i);
        product.setProductnumber(DigestUtils.md5Hex("hello"+i));
        product.setManufacturer("huawei");
        product.setProducepath("/test");
        product.setImagepath("/test");
        product.setIntime(new Date());
        product.setOperator("张三");
        product.setPuttime(new Date());
        list.add(product);

    }

    return list;

}
  • 写入excel
@Test
public void simpleWrite() {
    // 写法2
    String fileName = TestFileUtil.getPath() + "simpleWriteTest" + System.currentTimeMillis() + ".xlsx";
    // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
    // 如果这里想使用03 则 传入excelType参数即可
    EasyExcel.write(fileName, Product.class).sheet("测试01").doWrite(getData(10));
}

进阶

编写实体类

@TableName(value ="product")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Product implements Serializable {
    /**
     * 序号_自动生成
     */
    @TableId(type = IdType.AUTO)
    @ExcelProperty("序号")
    private Integer number;

    /**
     * 创建时间
     */
    @ExcelProperty("创建时间")
    private Date createtime;

    /**
     * 产品名称
     */
    @ExcelProperty("产品名称")
    private String productname;

    /**
     * 产品编号
     */
    @ExcelProperty("产品编号")
    private String productnumber;

    /**
     * 产品型号
     */
    @ExcelProperty("产品型号")
    private String manufacturer;

    /**
     * 产品位置
     */
    @ExcelProperty("产品位置")
    private String producepath;

    /**
     * 图片位置
     */
    @ExcelProperty("图片位置")
    private String imagepath;

    /**
     * 使用单位
     */
    @ExcelProperty("使用单位")
    private String unit;

    /**
     * 金额
     */
    @ExcelProperty("金额")
    private Integer money;

    /**
     * 入库时间
     */
    @ExcelProperty("入库时间")
    private Date intime;

    /**
     * 出库时间
     */
    @ExcelProperty("出库时间")
    private Date puttime;

    /**
     * 操作人
     */
    @ExcelProperty("操作人")
    private String operator;

    /**
     * 创建人
     */
    @ExcelProperty("创建人")
    private String createduser;

    /**
     * 备注
     */
    @ExcelProperty("备注")
    private String notes;

    /**
     * 产品数量
     */
    @ExcelProperty("产品数量")
    private Integer producedigit;

    /**
     * 产品单位
     */
    @ExcelProperty("产品单位")
    private String productunit;

    @TableField(exist = false)
    private static final long serialVersionUID = 1L;
}

批量写数据

操作步骤:1、实体类(如上述实体类)

2、生成数据方法

private List<Product> getData(int count) {

    List<Product> list = ListUtils.newArrayList();

    for (int i = 0; i < count; i++) {

        Product product = new Product();
        product.setCreatetime(new Date());
        product.setProductname("服务器00"+i);
        product.setProductnumber(DigestUtils.md5Hex("hello"));
        product.setManufacturer("huawei");
        product.setProducepath("/test");
        product.setImagepath("/test");
        product.setIntime(new Date());
        product.setOperator("张三");
        product.setPuttime(new Date());
        list.add(product);
    }
    return list;
}

3、批量写如excel方法

/重复多次写入(写到单个或者多个Sheet)
@Test
public void manyWrite() {
    // 方法1: 如果写到同一个sheet
    String fileName = "C:\\Users\\13631\\Desktop\\simpleWriteTest1702391756908.xlsx";
    // 这里 需要指定写用哪个class去写
    try (ExcelWriter excelWriter = EasyExcel.write(fileName, Product.class).build()) {
        // 这里注意 如果同一个sheet只要创建一次
        WriteSheet writeSheet = EasyExcel.writerSheet("测试").build();
         long star = System.currentTimeMillis();
        // 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来
        for (int i = 0; i < 5; i++) {
            // 分页去数据库查询数据 这里可以去数据库查询每一页的数据
            List<Product> data = getData(1000);
            excelWriter.write(data, writeSheet);
        }
        long end = System.currentTimeMillis();
        System.out.println("耗时:" + (end - star)/1000 + "秒");
    }
}

自定义模板写入excel

填充单行

填充集合

//根据模板填充数据
@Test
public void fillWrite() {
    // 方案2 分多次 填充 会使用文件缓存(省内存)
    String fileName = "C:\\Users\\13631\\Desktop\\模板写数据.xlsx";
    String templateFileName = "C:\\Users\\13631\\Desktop\\模板.xlsx";
    try (ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build()) {
        WriteSheet writeSheet = EasyExcel.writerSheet().build();
        excelWriter.fill(getData2(100), writeSheet);
    }
}

填充效果

自定义监听器

1、实体类(如上述实体类)

2、自定义监听器

Invoke和doAfterAllAnalysed是必选的

public class MyListener implements ReadListener<Product> {

    private TestMapper testMapper;
    private ArrayList<Product> list = new ArrayList<>();
    int sum=0;

    public MyListener(TestMapper testMapper) {
        this.testMapper = testMapper;
    }

    //每读一行,则调用该方法
    @Override
    public void invoke(Product product, AnalysisContext analysisContext) {
        sum++;
        list.add(product);
    }
    //每读完整个excel,则调用该方法
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        System.out.println("读取了"+sum+"行数据");
    }
}

@Test
void contextLoads() {
    String fileName = "C:\\Users\\13631\\Desktop\\simpleWriteTest1702391756908.xlsx";
    // 这里默认每次会读取100条数据 然后返回过来 直接调用使用数据就行
    // 具体需要返回多少行可以在`PageReadListener`的构造函数设置
    ExcelReader reader = EasyExcel.read(fileName, Product.class, new MyListener(new TestMapper())).build();
    ReadSheet sheet = EasyExcel.readSheet().build();
    reader.read(sheet);
}

  • 21
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

QGS-CD

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值