easyExcel解析数据,并将合并单元格的数据解析,30M的数据仅需8s

数据大小30M左右

耗费时间8秒

package io.renren.modules.tollstation.utils;

import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import io.renren.modules.tollstation.entity.TollStationRevenueEntity;
import io.renren.modules.tollstation.entity.TollStationTrafficEntity;
import io.swagger.models.auth.In;
import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author 李亚杰
 * @date 2024/4/24 15:49
 * @description LiyajieExcelUtil1
 */
public class LiyajieExcelUtil2 {
    public static void main(String[] args) throws Exception {
        File file = new File("C:\\Users\\liyajie\\IdeaProjects\\monthScore\\renren-admin\\src\\main\\resources\\2023年通行费收入统计表-税前(公司、路段)20240116.xlsx");
//        File file = new File("C:\\Users\\liyajie\\IdeaProjects\\monthScore\\renren-admin\\src\\main\\resources\\202301-流量——收费站出入口 (恢复的).xlsx");
//        File file = new File("C:\\Users\\liyajie\\IdeaProjects\\monthScore\\renren-admin\\src\\main\\resources\\学生.xlsx");
        long l1 = System.currentTimeMillis();
//        List<TollStationTrafficEntity> dispose = dispose(file, 1, 4, 4, 20000, TollStationTrafficEntity.class);
//        System.out.println(dispose.size());
        List<Integer> index= new ArrayList<>();
        index.add(0);
        index.add(1);
        readExcel(file, TollStationRevenueEntity.class, 1,4, 4);
//        readExcel(file);
        long l2 = System.currentTimeMillis();
        System.out.println("耗费时间"+(l2-l1));


    }

    /**
     * 读取Excel文件并将合并单元格的数据解析
     * @param file  excel文件
     * @param tClass    类Class对象
     * @param sheetIndex    sheet索引0代表第一张表
     * @param startIndex    起始位置,一般为表头行数
     * @param endIndex 结束位置
     * @param index     Excel的表格需要处理的合并单元格的列数,从0开始,0代表处理第一列的合并单元格数据,0,1代表处理第1,2列的合并单元格数据,以此类推
     */
    public static <T> List<T> readExcel(File file,Class<T> tClass,int sheetIndex,int startIndex,int endIndex,List<Integer> index) {
        List<T> userDataList = new ArrayList<>();
        EasyExcel.read(file, tClass, new AnalysisEventListener<T>() {
            @Override
            public void invoke(T userData, AnalysisContext analysisContext) {
                userDataList.add(userData);
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                // 所有数据解析完成后可以执行的操作,例如关闭流等
            }
        }).headRowNumber(startIndex).sheet(sheetIndex).doRead();
        List<T> tList = userDataList.subList(0, userDataList.size() - endIndex);

        final T[] t = (T[]) new Object[]{tList.get(0)};
            tList.forEach(o->{
                try {
                        copyNonNullValues(t[0],o,index);

                } catch (IllegalAccessException e) {
                    throw new RuntimeException(e);
                }
                t[0] =o;
            });
        return tList;
    }
    /**
     * 读取Excel文件
     * @param file  excel文件
     * @param tClass    类Class对象
     * @param sheetIndex    sheet索引0代表第一张表
     * @param startIndex    起始位置,一般为表头行数
     * @param endIndex 结束位置
     */
    public static <T> List<T> readExcel(File file,Class<T> tClass,int sheetIndex,int startIndex,int endIndex) {
        return readExcel(file,tClass,sheetIndex,startIndex,endIndex,null);
    }
    /**
     * 读取Excel文件
     * @param file  excel文件
     * @param tClass    类Class对象
     * @param sheetIndex    sheet索引0代表第一张表
     * @param startIndex    起始位置,一般为表头行数
     */
    public static <T> List<T> readExcel(File file,Class<T> tClass,int sheetIndex,int startIndex) {
        return readExcel(file,tClass,sheetIndex,startIndex,0,null);
    }
    /**
     * 读取Excel文件,默认读取第一张表
     * @param file  excel文件
     * @param tClass    类Class对象
     * @param startIndex    起始位置,一般为表头行数
     */
    public static <T> List<T> readExcel(File file, Class<T> tClass, int startIndex) {
        return readExcel(file,tClass,0,startIndex,0,null);
    }
    /**
     * 读取Excel文件,默认读取第一张表,默认表头只有一行
     * @param file  excel文件
     * @param tClass    类Class对象
     */
    public static <T> List<T> readExcel(File file,Class<T> tClass) {
        return readExcel(file,tClass,0,1,0,null);
    }
    /**
     * 读取Excel文件,默认读取第一张表,默认表头只有一行
     * @param file  excel文件
     */
    public static  List<Object> readExcel(File file) {
       return EasyExcel.read(file).sheet().doReadSync();
    }
    /**
     * 将s对象中的不为空的值赋值给t对象中为空的值
     * @param source s对象
     * @param target    t对象
     * @param index  需要赋值的属性的列数
     * @param <T>
     * @throws IllegalAccessException
     */
    public static <T> void copyNonNullValues(T source, T target,List<Integer> index) throws IllegalAccessException {
        if (index==null||index.size()==0) return;
        Class<?> sourceClass = source.getClass();
        Class<?> targetClass = target.getClass();

        // 确保source和target是同一类型或其子类
        if (!sourceClass.isAssignableFrom(targetClass) && !targetClass.isAssignableFrom(sourceClass)) {
            throw new IllegalArgumentException("Source and target objects must be of compatible types");
        }

        // 获取source对象的所有字段
        Field[] sourceFields = sourceClass.getDeclaredFields();
        //获取需要处理的列数
            for (int i : index) {
                Field sourceField = sourceFields[i];
            sourceField.setAccessible(true); // 允许访问私有字段

            // 获取target对象中对应的字段
            try {
                Field targetField = targetClass.getDeclaredField(sourceField.getName());
                targetField.setAccessible(true); // 允许访问私有字段

                // 获取source字段的值
                Object sourceValue = sourceField.get(source);

                // 如果source字段的值非空,且target字段的值为空,则复制值
                if (sourceValue != null && (targetField.get(target) == null || "".equals(targetField.get(target)))) {
                    targetField.set(target, sourceValue);
                }
            } catch (NoSuchFieldException e) {
                // 忽略target对象中不存在的字段
            }
        }
    }
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
可以通过实现EasyExcel的WriteHandler接口来实现相同数据合并单元格的功能。具体步骤如下: 1. 新建一个类实现WriteHandler接口,并重写对应的方法。 2. 在实现的方法中,通过Excel的API获取到要合并的单元格的起始行、起始列、结束行、结束列。可以使用Map来记录每一种相同数据的位置信息,然后再遍历Map合并单元格。 3. 使用EasyExcel的write方法时,通过指定Handler参数,将编写好的WriteHandler实例传递进去即可。 下面是示例代码: ```java public class MergeCellWriteHandler implements WriteHandler { private Map<String, List<CellRangeAddress>> mergeMap = new HashMap<>(); @Override public void row(int i, List<Object> list) { //处理行数据,将相同的数据合并单元格 String key = list.get(0).toString(); //以第一列为key if (mergeMap.containsKey(key)) { List<CellRangeAddress> cellRangeList = mergeMap.get(key); CellRangeAddress lastCellRange = cellRangeList.get(cellRangeList.size() - 1); if (i - lastCellRange.getLastRow() == 1) { //如果上一个单元格的结尾行是当前行的上一行,则可以合并单元格 lastCellRange.setLastRow(i); } else { cellRangeList.add(new CellRangeAddress(i, i, 0, list.size() - 1)); //如果不连续,则新建一个单元格范围 } } else { List<CellRangeAddress> cellRangeList = new ArrayList<>(); cellRangeList.add(new CellRangeAddress(i, i, 0, list.size() - 1)); mergeMap.put(key, cellRangeList); } } @Override public void sheet(int i) { } @Override public void start() { } @Override public void end() { //处理完整个sheet后,将记录的单元格范围进行合并 Sheet sheet = EasyExcel.writerSheet().build().getSheet(); for (Map.Entry<String, List<CellRangeAddress>> entry : mergeMap.entrySet()) { String key = entry.getKey(); List<CellRangeAddress> cellRangeList = entry.getValue(); for (CellRangeAddress cellRange : cellRangeList) { sheet.addMergedRegion(cellRange); } } } } ``` 使用方法: ```java EasyExcel.write("test.xlsx") .sheet() .registerWriteHandler(new MergeCellWriteHandler()) .head(head) .doWrite(data); ``` 其中head和data分别是表头和数据,可以从数据库或其他数据源中获取。要实现合并单元格要将第一列相同的数据合并。示例中以第一列为key,记录每一种相同数据所对应的单元格范围,最后进行合并。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

财大彭于晏

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

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

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

打赏作者

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

抵扣说明:

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

余额充值