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("模版错误,请重新上传");
}
相关推荐
零千叶39 分钟前
【面试】AI大模型应用原理面试题
java·设计模式·面试
坐吃山猪5 小时前
SpringBoot01-配置文件
java·开发语言
我叫汪枫6 小时前
《Java餐厅的待客之道:BIO, NIO, AIO三种服务模式的进化》
java·开发语言·nio
yaoxtao6 小时前
java.nio.file.InvalidPathException异常
java·linux·ubuntu
Swift社区7 小时前
从 JDK 1.8 切换到 JDK 21 时遇到 NoProviderFoundException 该如何解决?
java·开发语言
DKPT8 小时前
JVM中如何调优新生代和老生代?
java·jvm·笔记·学习·spring
phltxy8 小时前
JVM——Java虚拟机学习
java·jvm·学习
seabirdssss9 小时前
使用Spring Boot DevTools快速重启功能
java·spring boot·后端
喂完待续10 小时前
【序列晋升】29 Spring Cloud Task 微服务架构下的轻量级任务调度框架
java·spring·spring cloud·云原生·架构·big data·序列晋升