使用Java操作excel,EasyExcel的使用

383 阅读4分钟

一、介绍

EasyExcel 是一个基于 Apache POI,用于读写 Excel 的 Java 简易工具库。它能在尽可能节约内存的情况下,读写 Excel。与其他基于 Apache POI 的 Excel 工具库相比,EasyExcel 在处理大量数据时,能显著减少内存消耗,避免发生内存溢出错误OOM(OutOfMemoryError)。

二、使用

需求:

我这次使用easyExcel是想实现将一个Excel文件中的数据读取出来,经过处理后再写入到另一个excel中。

需要读取的数据样式(‘客户’那个sheet页只是我生成数据时使用的,本次使用easyexcel操作excel的时候并没有使用):

1716726018509.png

想生成的数据样式(两个Sheet页):

1716726096599.png

1716726206473.png

生成数据与原数据相比是增加了三列和一个sheet页,第二个Sheet中的数据就是将账单表Sheet页中的数据按照客户分别计算重量、数量、货款

1.导入pom依赖

首先导入easyexcel的依赖,这里我也导入了lombok的依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.3.2</version>
</dependency><dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.0</version>
</dependency>

2.创建实体类

easyexcel可以将表格中的每一行看作一个对象,因此我们先创建对应的实体类

想要读取的excel的实体类

@Data
public class Bill {
    /**
     * 日期格式需要是String类型 @DateTimeFormat注解才能生效
     * @ExcelProperty(value = "日期",index = 0) value表示这个属性在表格中的列名,index表示列的位置
     */
    @ExcelProperty(value = "日期",index = 0)
    @DateTimeFormat("yyyy-MM-dd")
    private String dateTime;
    @ExcelProperty(value = "客户",index = 1)
    private String customer;
    @ExcelProperty(value = "农户",index = 2)
    private String farmer;
    @ExcelProperty(value = "数量",index = 3)
    private Integer num;
    @ExcelProperty(value = "单重",index = 4)
    private Double singleWeight;
    @ExcelProperty(value = "额外重量",index = 5)
    private Double additionalWeight;
    @ExcelProperty(value = "单价",index = 6)
    private Double singlePrice;
}

想要写入的excel的对象的实体类sheet1

因为sheet1中的数据与读取的那个表格中的数据相比只是增加了三列,因此直接继承Bill类

@Data
public class BillOut extends Bill{
    /**
     * 总重量
     */
    @ExcelProperty(value = "总重量",index = 7)
    private Double sumWeight;
    /**
     * 货款
     */
    @ExcelProperty(value = "货款",index = 8)
    private Double customerAmount;
    /**
     * 农户货款
     */
    @ExcelProperty(value = "农户货款",index = 9)
    private Double farmerAmount;
}

想要写入的excel的对象的实体类sheet2

@Data
public class BillSum {
    /**
     * 客户名称
     */
    @ExcelProperty("客户")
    private String customer;
    /**
     * 客户当天的数量
     */
    @ExcelProperty("客户收货数量")
    private Integer customerNum;
    /**
     * 客户当天的货款
     */
    @ExcelProperty("客户总货款")
    private Double customerAmount;
    /**
     * 客户当天的总重量
     */
    @ExcelProperty("总重量")
    private Double customerSumWeight;
}

3.读取excel

    /**
     * 读取Excel的数据
     * @param fileName
     * @return
     */
    public static List<Bill> getData(String fileName){
        // 存放读取出来的数据
        final List<Bill> list = new ArrayList<Bill>();
        // fileName是需要读取的文件路径
        EasyExcel.read(fileName)
//                .head() 用来设置表头对应的类 也就是每一行数据对应的那个对象的类
                .head(Bill.class)
//                .sheet() 设置想要读取的数据在文件中的哪个sheet页面 0-表示第一个sheet页
                .sheet(0)
//                创建一个读监听器(使用匿名内部类的方式)
                .registerReadListener(new AnalysisEventListener<Bill>() {
//                    重新invoke方法,easyexcel是一行一行读取数据的,相当于对每个数据都执行一遍这个操作
                    public void invoke(Bill bill, AnalysisContext analysisContext) {
                        list.add(bill);
                    }
//                  重写doAfterAllAnalysed 这个是读完所有数据后最后执行的方法
                    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                        System.out.println("数据读取完毕");
                    }
                })
//                最后执行doRead方法执行
                .doRead();
        return list;
    }

4.写入excel

    /**
     * 处理数据 写入Excel
     *  Sheet1 :所有货的数据
     *  Sheet2 : 每个客户的和
     * @param preData
     */
    public static void writeSheet(List<Bill> preData,String outFileName){
        // 存放Sheet1需要的数据
        List<BillOut> sheet1Data = new ArrayList<BillOut>();
        // 存放Sheet2需要的数据 -- 因为是按客户维度计算一些数据,所以以客户名为key,将数据放入到map中 最后返回的时候只需要返回value集合就可以
        Map<String,BillSum> customerMap = new HashMap<String, BillSum>();
        for (Bill bill:preData){
            BillOut billOut = new BillOut();
            // 将读取到的数据copy到需要写入的数据中
            BeanUtil.copyProperties(bill,billOut);
            // 1.处理Sheet1中的数据
            // 计算总重量
            Double sumWeight = billOut.getNum()*billOut.getSingleWeight()+billOut.getAdditionalWeight();
            billOut.setSumWeight(sumWeight);
            // 计算货款
            Double customerAmount = sumWeight*billOut.getSinglePrice();
            billOut.setCustomerAmount(customerAmount);
            // 计算农户货款
            Double farmerAmount = sumWeight*(billOut.getSinglePrice()-BillConstant.DEDUCT_MONEY);
            billOut.setFarmerAmount(farmerAmount);
            // 2.处理Sheet2中的数据
            BillSum billSum;
            if (customerMap.containsKey(billOut.getCustomer())){
                billSum = customerMap.get(billOut.getCustomer());
            }else{
                billSum = new BillSum();
                billSum.setCustomer(billOut.getCustomer());
                billSum.setCustomerAmount(0.0);
                billSum.setCustomerNum(0);
                billSum.setCustomerSumWeight(0.0);
                customerMap.put(billSum.getCustomer(),billSum);
            }
            // 客户数量 = 该客户下的所有数量和
            billSum.setCustomerNum(billSum.getCustomerNum()+billOut.getNum());
            billSum.setCustomerSumWeight(billSum.getCustomerSumWeight()+billOut.getSumWeight());
            billSum.setCustomerAmount(billSum.getCustomerAmount()+billOut.getCustomerAmount());
            // 将Sheet1中的数据放入sheet1的list中
            sheet1Data.add(billOut);
        }
        // 写入Excel
        ExcelWriter writeWorkbook = EasyExcel.write(outFileName).build();
        // sheet1的builder
        ExcelWriterSheetBuilder sheetBuilder1 = EasyExcel.writerSheet(0,"账单表").head(BillOut.class);
        // sheet2的builder
        ExcelWriterSheetBuilder sheetBuilder2 = EasyExcel.writerSheet(1,"客户账单表").head(BillSum.class);
​
        WriteSheet writeSheet1 = sheetBuilder1.build();
        WriteSheet writeSheet2 = sheetBuilder2.build();
        // 指定将数据写入到哪个sheet中
        writeWorkbook.write(sheet1Data,writeSheet1);
        writeWorkbook.write(customerMap.values(),writeSheet2);
        // 结束
        writeWorkbook.finish();
    }

5.运行

    public static void main(String[] args) {
        String fileName = "E:\笔记\学习笔记\excel学习笔记\测试\数据校验test2.xlsx";
        String outFileName = "E:\笔记\学习笔记\excel学习笔记\测试\导出数据test3.xlsx";
        List<Bill> bills = getData(fileName);
        writeSheet(bills,outFileName);
    }