java通用Excel解析工具类

为了创建一个通用的Excel解析工具类,我们需要考虑以下几点:

  1. 泛型支持,以便能够处理不同类型的Java对象。
  2. 映射机制,以将Excel列映射到Java对象的字段。
  3. 错误处理和日志记录。

以下是一个简化的通用Excel解析工具类的示例

<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>

@Data
public class MyEntity {/*** name*/@ExcelColumn(index = 0, name = "name")private long name;/***age*/@ExcelColumn(index = 1, name = "age")private long age;
}

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 ExcelColumn {int index() default -1; // 列的索引,从0开始String name() default ""; // 列名,可以与Excel中的标题对应
}
import com.alibaba.fastjson.JSON;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.*;public class ExcelParserUtil {/*** excel解析工具类** @param inputStream* @param clazz* @param <T>* @return*/public static <T> List<T> parseExcel(InputStream inputStream, Class<T> clazz) throws Exception {List<T> result = new ArrayList<>();List<String> failReasonList = new ArrayList<>();int execRow = 1;try (Workbook workbook = new XSSFWorkbook(inputStream)) {Sheet sheet = workbook.getSheetAt(0); // 假设我们只处理第一个工作表Row headerRow = sheet.getRow(0); // 假设第一行是标题行// 读取实体类的字段注解,构建字段名和列索引的映射Map<String, Integer> fieldIndexMap = new HashMap<>();Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {ExcelColumn excelColumn = field.getAnnotation(ExcelColumn.class);if (excelColumn != null && excelColumn.index() >= 0) {field.setAccessible(true);fieldIndexMap.put(field.getName(), excelColumn.index());}}// 跳过标题行,从第二行开始解析数据for (int i = 1; i <= sheet.getLastRowNum(); i++) {Row row = sheet.getRow(i);T instance = clazz.getDeclaredConstructor().newInstance();for (Map.Entry<String, Integer> entry : fieldIndexMap.entrySet()) {try {String fieldName = entry.getKey();int columnIndex = entry.getValue();Cell cell = row.getCell(columnIndex);if (cell != null) {Field field = clazz.getDeclaredField(fieldName);setFieldValue(instance, field, cell);}} catch (Exception e) {failReasonList.add("第" + execRow + "行解析错误:" + e.getMessage());}}execRow++;result.add(instance);}} catch (Exception e) {throw new Exception("parseExcel->数据解析错误:", e);}if (CollectionUtils.isNotEmpty(failReasonList)) {//System.out.println(JSON.toJSON(failReasonList));throw new Exception(JSON.toJSONString(failReasonList.subList(0, failReasonList.size() > 20 ? 20 : failReasonList.size())));}return result;}private static void setFieldValue(Object instance, Field field, Cell cell) throws IllegalAccessException, InvocationTargetException {Class<?> fieldType = field.getType();field.setAccessible(true);// 总是将Cell设置为STRING类型,以确保我们可以获取字符串值cell.setCellType(CellType.STRING);String cellValue = cell.getStringCellValue();if (String.class.equals(fieldType)) {field.set(instance, cell.getStringCellValue());} else if (Integer.class.equals(fieldType) || int.class.equals(fieldType)) {field.setInt(instance, Integer.parseInt(cellValue));} else if (Long.class.equals(fieldType) || long.class.equals(fieldType)) {field.setLong(instance, Long.parseLong(cellValue));} else if (Double.class.equals(fieldType) || double.class.equals(fieldType)) {field.setDouble(instance, Double.parseDouble(cellValue));} else if (Boolean.class.equals(fieldType) || boolean.class.equals(fieldType)) {field.setBoolean(instance, Boolean.parseBoolean(cellValue));} else {throw new RuntimeException("Unsupported field type: " + fieldType.getName());}}public static void main(String[] args) throws FileNotFoundException {// 假设你有一个方法可以从某个地方获取输入流,这里我们用一个示例输入流代替ExcelParserUtil parser = new ExcelParserUtil();File file = new File("/Users/xxx/Downloads/xxx.xlsx"); // 替换为你的文件路径InputStream inputStream = new FileInputStream(file);try {if (inputStream != null) {List<MyEntity> entityList = parser.parseExcel(inputStream, MyEntity.class);// 输出解析结果for (MyEntity entity : entityList) {System.out.println(entity.toString());}} else {System.out.println("无法找到或加载Excel文件。");}} catch (Exception e) {e.printStackTrace();}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/742408.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mybatis-Plus实现Service封装

文章目录 5.1 MP封装Service介绍5.1.1 说明5.1.2 实现流程5.1.3 核心API介绍 5.2 MP封装Service快速入门5.2.1 定义服务扩展接口5.2.2 定义服务实现5.2.3 测试测试 5.3 MP封装Service实现CRUD操作 5.1 MP封装Service介绍 5.1.1 说明 MybatisPlus为了开发更加快捷&#xff0c;…

C#使用Stack<T>类进行堆栈设计

目录 一、涉及到的知识点 1.栈定义 2.Stack类 二、 使用Stack<T>类进行堆栈设计 1.创建一个新的Stack实例 2.然后&#xff0c;可以使用Push方法将元素添加到堆栈中 3.使用Pop方法从栈顶删除一个元素 4.使用Peek方法查看堆栈顶部的元素 三、实例 一、涉及到的知识…

透视Docker容器:全方位解读基本概念、特性及实战命令全解

Docker容器,作为当代软件开发与部署领域的革新者,正逐步重塑IT行业的基础设施格局。本文旨在深入浅出地阐述Docker容器的基本概述、独特特性以及常用命令的实战操作,助您轻松掌握这一现代技术工具,最后,我们将围绕Docker容器的前沿应用与最佳实践展开讨论。 一、Docker容…

前端去除网页水印

按F12&#xff0c;打开开发者工具面板&#xff0c;然后直接在样式搜索backgroud 然后直接取消backgroud 的复选框即可。

【Linux】-Linux下的软件商店yum工具介绍(linux和windows互传文件仅仅一个拖拽搞定!!!!)

目录 1.Linux 软件包管理器yum 1.1快速认识yum 1.2 yumz下载方式&#xff08;如何使用yum进行下载&#xff0c;注意下载一定要是root用户或者白名单用户&#xff08;可提权&#xff09;&#xff09; 1.2.1下载小工具rzsz 1.2.2 rzsz使用 1.2.2查看软件包 1.3软件的卸载 2.yum生…

UE5 局域网联机,寻找会话失败。

目录 参考资料&#xff1a; 尝试解决办法 1.1在【项目名.Build.cs】脚本中添加该行&#xff0c;添加后关闭编辑器&#xff0c;重新生成解决方案。​编辑 2.检查是否在同一个C类子网 参考资料&#xff1a; 1.Cant find session in LAN - Programming & Scripting / Mul…

【C语言】字符串函数上

&#x1f451;个人主页&#xff1a;啊Q闻 &#x1f387;收录专栏&#xff1a;《C语言》 &#x1f389;道阻且长&#xff0c;行则将至 前言 这篇博客是字符串函数上篇&#xff0c;主要是关于长度不受限制的字符串函数&#xff08;strlen,strcpy,strcat,strcm…

“我快无聊死了”用英语怎么说?柯桥英语口语学习,成人零基础学外语

每日一句 Im bored to death. 我快无聊死了。 单词解析&#xff1a; bored / bɔːd / adj.无聊的&#xff0c;厌倦的 bored to d15857575376eath&#xff1a;指非常无聊或厌烦&#xff0c;达到了极点的程度。 "bored" 和 "boring" 都与无聊相关&#…

Docker镜像与容器的亲密对话:深度剖析两者内在关联与实战演绎

在Docker技术的广阔疆域中,镜像和容器无疑是两大核心支柱,它们之间的紧密关系与协同工作深刻塑造了现代软件开发与部署的新范式。本文将深入浅出地阐述Docker镜像与容器之间的本质联系,并通过实战案例透彻解析它们如何在实际应用中交融互动,最后,我们将就二者的关系与实践…

2024-01-重学MySQL

0 SQL 0.1 SQL分类 SQL语言在功能上主要分为如下三大类&#xff1a; DDL&#xff08;Data Definition Languages&#xff0c;数据定义语言&#xff09;&#xff1a;这些语言定义了不同的数据库、表、视图、索引等数据库对象&#xff0c;还可以用来创建、删除、修改数据库和数…

漏洞发现-漏扫项目篇武装BURP浏览器插件信息收集分析辅助

知识点 1、插件类-武装BurpSuite-漏洞检测&分析辅助 2、插件类-武装谷歌浏览器-信息收集&情报辅助 章节点&#xff1a; 漏洞发现-Web&框架组件&中间件&APP&小程序&系统 扫描项目-综合漏扫&特征漏扫&被动漏扫&联动漏扫 Poc开发-Ymal语…

产品测试方案:视频接入平台并发性能测试方案和报告(即150路视频并发流媒体服务器模块的性能测试方案和报告)

目 录 一、测试目的&#xff1a; 二、测试方案&#xff1a; 2.1、测试思路 2.2、拓扑图 三、测试环境 3.1 服务器配置 3.2 网络摄像机列表 3.3 测试软件 四、测试流程 4.1 H.264并发测试&#xff1a; 4.1.1老版本srsout3.10并发测试 4.1.2 新版本srsout…

【PyTorch][chapter 22][李宏毅深度学习]【无监督学习][ WGAN]【理论二】

前言&#xff1a; 本篇主要参考《Wasserstein GAN and the Kantorovich-Rubinstein Duality》 重点介绍一下 WGAN 的损失函数 是如何通过 Wasserstein Distance 变换过来的。 分为5步&#xff1a; 我们首先建立Wasserstein Distance 极小值形式&#xff0c; 经过对…

代码随想录算法训练营第三十二天|LeetCode122 买卖股票的最佳时机II 、LeetCode55 跳跃游戏、

122.买卖股票的最佳时机II 为了获得最大利润&#xff0c;我们可以将每一个局部峰值和局部谷值之间的差值累加起来。如果第 i 天的股票价格比第 i-1 天高&#xff0c;则将这两天的股票进行买卖&#xff0c;即累加差值 (prices[i] - prices[i-1])&#xff0c;否则不进行交易。 …

Gradio测试-->Gradio映射-->可视化GPT4V API-->Gemini Pro、Claude和Qwen的API

Gradio测试 import gradio as gr import timedef demo_test(text, imageNone):time.sleep(1) # 正确的暂停调用return text, image if image is not None else None# 创建 Gradio 接口 iface gr.Interface(fndemo_test,inputs[gr.Textbox(label"输入文本"), gr.Im…

零基础学习JS--基础篇--函数

定义函数 一个函数定义&#xff08;也称为函数声明&#xff0c;或函数语句&#xff09;由 function 关键字&#xff0c;并跟随以下部分组成&#xff1a; 函数名称。函数参数列表&#xff0c;包围在括号中并由逗号分隔。定义函数的 JavaScript 语句&#xff0c;用大括号括起来…

向ChatGPT高效提问模板

PS: ChatGPT无限次数&#xff0c;无需魔法&#xff0c;登录即可使用,网页打开下面 tj4.mnsfdx.net [点击跳转链接](http://tj4.mnsfdx.net/) 我想请你XXXX&#xff0c;请问我应该如何向你提问才能得到最满意的答案&#xff0c;请提供全面、详细的建议&#xff0c;针对每一个建…

三权分立学习

1、什么是三权 三权指的是配置、授权、审计。 配置指对应用系统进行配置&#xff0c;使之能正常运行&#xff1b;授权指对使用应用系统的账号进行管理&#xff0c;在此过程中提高应用系统的安全等级&#xff1b;审计指对上述两项工作进行监督指导&#xff0c;及时上报危险的操…

微任务与宏任务的区别

一. 什么是宏任务&#xff08;MacroTask&#xff09; 宏任务包括&#xff1a;setTimeout setInterval Ajax DOM事件&#xff0c; 宏任务是由宿主&#xff08;浏览器、Node&#xff09;发起的&#xff0c;宏任务&#xff0c;可以理解为每次执行栈执行的代码就是一个宏任务&…

王道机试C++第6章 数学问题和22年蓝桥杯省赛选择题Day34

6.1 进制转换 二进制数&#xff08;十转二&#xff09; 习题描述 大家都知道&#xff0c;数据在计算机里中存储是以二进制的形式存储的。 有一天&#xff0c;小明学了C语言之后&#xff0c;他想知道一个类型为unsigned int 类型的数字&#xff0c;存储在计算机中的二进制串是…