Java使用FastExcel实现Excel文件导入

依赖配置 (Maven pom.xml)

XML 复制代码
<dependencies>
    <!-- FastExcel 核心库 -->
    <dependency>
        <groupId>cn.idev.excel</groupId>
        <artifactId>fastexcel</artifactId>
        <version>1.0.0</version>
    </dependency>
    
    <!-- Apache POI 依赖 -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>5.2.3</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>5.2.3</version>
    </dependency>
</dependencies>

映射实体类SetMealDetailsVo

java 复制代码
package com.fantaibao.module.vo.appDish;

import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.write.style.ColumnWidth;
import cn.idev.excel.annotation.write.style.HeadFontStyle;
import cn.idev.excel.annotation.write.style.HeadStyle;
import cn.idev.excel.enums.BooleanEnum;
import cn.idev.excel.enums.poi.FillPatternTypeEnum;
import com.fantaibao.module.po.DishAppManagementOriginal;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.math.BigDecimal;
import java.util.Date;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ExcelIgnoreUnannotated
@HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 22)
@HeadFontStyle(fontName = "Microsoft YaHei", fontHeightInPoints = 11, bold = BooleanEnum.TRUE)
public class SetMealDetailsVo {
    /**
     * 套餐ID
     */
    @ColumnWidth(30)
    @ExcelProperty("套餐ID")
    private String code;
    /**
     * 标准套餐名称
     */
    @ColumnWidth(30)
    @ExcelProperty("标准套餐名称")
    private String menuName;
    /**
     * 套餐定价
     */
    private BigDecimal price;
    /**
     * 套餐定价
     */
    @ColumnWidth(20)
    @ExcelProperty("套餐定价")
    private String priceStr;

    /**
     * 套餐毛利率(%)
     */
    @ColumnWidth(20)
    @ExcelProperty("套餐毛利率(%)")
    private String grossMarginStr;
    /**
     * 毛利率(%)
     */
    private BigDecimal grossMargin;

    /**
     * 明细菜编码
     */
    @ColumnWidth(30)
    @ExcelProperty("明细菜编码")
    private String detailsCode;
    /**
     * 明细菜品名称
     */
    @ColumnWidth(30)
    @ExcelProperty("明细菜品名称")
    private String detailsMenuName;
    /**
     * 明细菜单位
     */
    @ColumnWidth(30)
    @ExcelProperty("明细菜品单位")
    private String detailsUnit;
    /**
     * 明细菜定价
     */
    @ColumnWidth(20)
    @ExcelProperty("明细菜定价")
    private String detailsPriceStr;

    private BigDecimal detailsPrice;

    /**
     * 明细菜毛利率(%)
     */
    @ColumnWidth(20)
    @ExcelProperty("明细菜毛利率(%)")
    private String detailsGrossMarginStr;
    /**
     * 明细菜毛利率(%)
     */
    private BigDecimal detailsGrossMargin;

    /**
     * 明细菜分类
     */
    @ColumnWidth(20)
    @ExcelProperty("明细菜分类")
    private String detailsClass;


}

自定义监听器CustomSheetListener(带校验表头)

java 复制代码
package com.fantaibao.listener;

import cn.hutool.core.collection.CollUtil;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.context.AnalysisContext;
import cn.idev.excel.metadata.data.ReadCellData;
import cn.idev.excel.read.listener.ReadListener;
import cn.idev.excel.util.StringUtils;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

@Slf4j
@Getter
@RequiredArgsConstructor
public class CustomSheetListener<T> implements ReadListener<T> {

    /**
     * 返回最终解析的数据
     */
    private List<T> dataList;

    private List<String> fields;

    public CustomSheetListener(List<T> dataList, Class clazz) {
        this.dataList = dataList;
        this.fields = getFields(clazz);
    }

    /**
     * 根据class通过反射获取字段上@ExcelProperty注解的值
     *
     * @param clazz 类名
     * @return 注解的值
     */
    private static List<String> getFields(Class clazz) {
        List<String> fields = CollUtil.newArrayList();
        //根据class通过反射获取字段上@ExcelProperty注解的值
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field field : declaredFields) {
            ExcelProperty annotation = field.getAnnotation(ExcelProperty.class);
            if (annotation != null) {
                String[] value = annotation.value();
                // 添加到列表中
                fields.addAll(Arrays.asList(value));
            }
        }
        return fields;
    }

    @Override
    public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
        // 在这里检查表头是否正确
        for (Map.Entry<Integer, ReadCellData<?>> entry : headMap.entrySet()) {
            String headerValue = entry.getValue().getStringValue();
            // 根据你的需求检查表头值
            if (!isValidHeader(headerValue)) {
                throw new RuntimeException("模版错误,请重新上传");
            }
        }
        //
        if(!fields.isEmpty() && context.readSheetHolder().getHeadRowNumber()-1 == context.readSheetHolder().getRowIndex()){
            throw new RuntimeException("模版错误,请重新上传");
        }
    }

    @Override
    public void invoke(T data, AnalysisContext context) {
        dataList.add(data);
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        log.info("excel解析完成,sheet名为:{}", context.readSheetHolder().getSheetName());
    }

    /**
     *
     * @param header 表头名称
     * @return 是否存在 存在则移除掉
     */
    private boolean isValidHeader(String header) {
        if (StringUtils.isBlank(header)) {
            return true;
        }
        if(this.fields.contains(header)){
            fields.removeIf(field->field.equals(header));
            return true;
        }
        return false;
    }
}

业务菜调用

java 复制代码
//fileUrl是文件全路径(我这里是腾讯云OSS文件路径)
List<SetMealDetailsVo> setMealDetails = CollUtil.newArrayList();
try {
	EasyExcel.read(new URL(fileUrl).openStream(),
					SetMealDetailsVo.class,
					new CustomSheetListener(setMealDetails, SetMealDetailsVo.class))
			.sheet(0)
			.doRead();
} catch (Exception e) {
	throw new RuntimeException("模版错误,请重新上传");
}
相关推荐
青衫码上行3 分钟前
【从0开始学习Java | 第22篇】反射
java·开发语言·学习
superlls12 分钟前
(Spring)Spring Boot 中 @Valid 与全局异常处理器的联系详解
java·spring boot·后端
我星期八休息1 小时前
C++智能指针全面解析:原理、使用场景与最佳实践
java·大数据·开发语言·jvm·c++·人工智能·python
摇滚侠1 小时前
Spring Boot 3零基础教程,WEB 开发 整合 Thymeleaf 笔记36
java·spring boot·笔记
大猫会长1 小时前
docker安装php+apache
java·开发语言
野生技术架构师1 小时前
JAVA 架构师面试题含答案:JVM+spring+ 分布式 + 并发编程
java·jvm·spring
瑞士卷@1 小时前
MyBatis入门到精通(Mybatis学习笔记)
java·数据库·后端·mybatis
梵得儿SHI1 小时前
Java 反射机制深度剖析:性能与安全性的那些坑
java·开发语言·安全·反射·动态代理·性能·反射机制
虫小宝1 小时前
Java分布式架构下的电商返利APP技术选型与架构设计实践
java·分布式·架构
007php0071 小时前
百度面试题解析:Zookeeper、ArrayList、生产者消费者模型及多线程(二)
java·分布式·zookeeper·云原生·职场和发展·eureka·java-zookeeper