【工具类】Excel 多 Sheet 导入工具类

news/2024/5/19 2:44:00 标签: excel, 解析, 工具类, 反射, java

使用自定义注解 + 反射 + 泛型 + 封装,实现统一读取

自定义注解,Excel 作用于属性-Excel 列名,ExcelTarget 作用于类-ExcelSheet名

java">import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface Excel {
    String name();
}

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface ExcelTarget {
    String name();
}
java">import com.excel.tool.putuo.annotation.Excel;
import com.excel.tool.putuo.annotation.ExcelTarget;
import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 【工具类】Excel 多 Sheet 导入工具类
 *
 * @author jason
 */
public class ExcelSheetUtil {

    /**
     * 获取 Sheet 名字
     */
    public static <T> String getSheetName(Class<T> clazz) {
        return AnnotationUtil.getAnnotationValue(clazz, ExcelTarget.class, "name");
    }

    /**
     * 读取多个sheet
     *
     * @param inputStream
     * @param classList
     * @return
     */
    public static Map<String, List<?>> readExcelList(InputStream inputStream, List<Class<?>> classList) {
        Map<String, List<?>> sheetMap = new HashMap<>();

        // 解决 InputStream 流只能读一次的问题,复制一个 ByteArrayOutputStream
        ByteArrayOutputStream cacheInputStream = new ByteArrayOutputStream();
        IoUtil.write(cacheInputStream, true, IoUtil.readBytes(inputStream));
        classList.forEach(tClass -> {
            String sheetName = AnnotationUtil.getAnnotationValue(tClass, ExcelTarget.class, "name");
            InputStream inputStreamSingleton = new ByteArrayInputStream(cacheInputStream.toByteArray());
            List<?> excelData3List = readExcelList(sheetName, inputStreamSingleton, tClass);
            sheetMap.put(sheetName, excelData3List);
        });
        return sheetMap;
    }

    /**
     * 读取单个sheet
     *
     * @param sheetName
     * @param inputStream
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> List<T> readExcelList(String sheetName, InputStream inputStream, Class<T> clazz) {
        ExcelReader excelReader = ExcelUtil.getReader(inputStream, sheetName);
        List<Map<String, Object>> mapList = excelReader.read(0, 0, Integer.MAX_VALUE);
        excelReader.close();
        return Optional.ofNullable(mapList)
                .orElse(new ArrayList<>())
                .stream()
                .map(itemMap -> {
                    T excelData = ReflectUtil.newInstance(clazz);
                    Field[] fields = ReflectUtil.getFields(clazz);
                    for (Field field : fields) {
                        String key = AnnotationUtil.getAnnotationValue(field, Excel.class, "name");
                        String value = StrUtil.toStringOrNull(itemMap.get(key));
                        ReflectUtil.setFieldValue(excelData, field, value);
                    }
                    return excelData;
                })
                .collect(Collectors.toList());
    }

}

使用

java">import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import com.excel.tool.putuo.excel.ExcelData0;
import com.excel.tool.putuo.excel.ExcelData1;
import com.excel.tool.putuo.excel.ExcelData2;
import com.excel.tool.putuo.excel.ExcelData3;
import com.excel.tool.putuo.util.ExcelSheetUtil;
import lombok.SneakyThrows;

import java.io.File;
import java.io.InputStream;
import java.util.List;
import java.util.Map;

public class TestMain {

    public static void main(String[] args) {
        File xlsx = FileUtil.file("数据11.21.xlsx");

        TestMain.startExcel(FileUtil.getInputStream(xlsx));
    }

    @SneakyThrows
    public static <T> void startExcel(InputStream inputStream) {
        List<Class<?>> classList = CollectionUtil.newArrayList(
                ExcelData0.class,
                ExcelData1.class,

                ExcelData2.class,
                ExcelData3.class
        );

        Map<String, List<?>> sheetMap = ExcelSheetUtil.readExcelList(inputStream, classList);

        List<ExcelData0> excelData0List = (List<ExcelData0>) sheetMap.get(ExcelSheetUtil.getSheetName(ExcelData0.class));
        List<ExcelData1> excelData1List = (List<ExcelData1>) sheetMap.get(ExcelSheetUtil.getSheetName(ExcelData1.class));
        List<ExcelData2> excelData2List = (List<ExcelData2>) sheetMap.get(ExcelSheetUtil.getSheetName(ExcelData2.class));
        List<ExcelData3> excelData3List = (List<ExcelData3>) sheetMap.get(ExcelSheetUtil.getSheetName(ExcelData3.class));

        System.out.println();
    }

}

实体定义

java">import com.excel.tool.putuo.annotation.Excel;
import com.excel.tool.putuo.annotation.ExcelTarget;
import lombok.Data;
import lombok.experimental.Accessors;

@Data
@Accessors(chain = true)
@ExcelTarget(name = "整表")
public class ExcelData0 {

    @Excel(name = "序号")
    private String num;

    @Excel(name = "来源")
    private String mediaType;

    @Excel(name = "发布时间")
    private String publishTime;

    @Excel(name = "作者")
    private String author;

    @Excel(name = "标题")
    private String title;

    @Excel(name = "摘要")
    private String digest;

    @Excel(name = "原文链接")
    private String link;

}

源码:https://gitee.com/zhaomingjian/workspace_luoan_demo/tree/master/excel-tool/src/main/java/com/excel/tool/putuo


http://www.niftyadmin.cn/n/5261058.html

相关文章

052:vue重新发布,软件热更新方面的一点经验示例

第052个 查看专栏目录: VUE ------ element UI 专栏目标 在vue和element UI联合技术栈的操控下&#xff0c;本专栏提供行之有效的源代码示例和信息点介绍&#xff0c;做到灵活运用。 &#xff08;1&#xff09;提供vue2的一些基本操作&#xff1a;安装、引用&#xff0c;模板使…

华为OD机试 - 石头剪刀布游戏(Java JS Python C)

题目描述 石头剪刀布游戏有 3 种出拳形状:石头、剪刀、布。分别用字母A、B、C表示。 游戏规则: 出拳形状之间的胜负规则如下: A > B; B > C; C > A; ">" 左边一个字母,表示相对优势形状。右边一个字母,表示相对劣势形状。 当本场次中有且仅有…

【计算机视觉】SIFT

在边缘提取的时候&#xff0c;用高斯一阶导对信号进行卷积&#xff0c;响应值最大的就是边界如果用高斯二阶导对信号进行卷积&#xff0c;0点就是边界点&#xff08;二阶导等于0的点&#xff0c;对应一阶导的极值点&#xff09; 如果用高斯二阶导在不同的信号上进行卷积&#x…

[ 云计算 | Azure 实践 ] 在 Azure 门户中创建 VM 虚拟机并进行验证

文章目录 一、前言二、在 Azure Portal 中创建 VM三、验证已创建的虚拟机资源3.1 方法一&#xff1a;在虚拟机服务中查看验证3.1 方法二&#xff1a;在资源组服务中查看验证 四、文末总结 一、前言 本文会开始创建新系列的专栏&#xff0c;专门更新 Azure 云实践相关的文章。 …

Android--Jetpack--数据库Room详解二

本是青灯不归客&#xff0c;却因浊酒恋红尘 一&#xff0c;基本使用 关于Room数据库的基本使用&#xff0c;请参考文章Android--Jetpack--数据库Room详解一-CSDN博客 二&#xff0c;Room与ViewModle,LiveData的结合使用 LiveData与ViewModle的使用&#xff0c;请参考文章Andr…

汽车网络安全--关于UN R155认证的思考

1.UN R155概述 2020年6月25日,联合国颁布了全球首个汽车网络安全强制性法规 -- UN 155,详细规定了关于评估网络安全措施的审核条款、制造商和供应商降低网络安全风险的方法以及实施风险评估的义务等。 法规适用于与信息安全相关的M类(4轮及以上载客汽车)、N类(四轮载货汽车)…

ARM按键中断

do_irq.c 判断中断号 #include "key_it.h" extern void printf(const char *fmt, ...); unsigned int i 0; void do_irq(void) {// 获取中断号&#xff0c;根据中断号的不同进行不同的中断处理int irqno;irqno GICC->IAR & 0x3ff;switch (irqno){case 99:…

第五题:加减(JavaPythonC++实现)【第六届传智杯-新增场次-程序设计挑战赛解题分析详解复盘】

本文仅为【2023传智杯-第二场】第六届传智杯程序设计挑战赛-题目解题分析详解的解题个人笔记,个人解题分析记录。 本文包含:第六届传智杯程序设计挑战赛题目、解题思路分析、解题代码、解题代码详解(Java&Python&C++实现) 文章目录 更新进度记录第五题:加减(Java…