Java 读取excel文件
导入:
先导入依赖:
<!-- 文件上传 -->
<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpmime</artifactId><version>4.5.7</version>
</dependency>
<!-- JSON -->
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.41</version>
</dependency>
<!-- POI -->
<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.16</version>
</dependency> 
1、获取想要上传excel文件的路径
2、获得路径后,通过路径定位生成数据流,使用FileInputStream方法读取路径对应文件的原始字节流。
//根据路径生成 FileInputStream字节流
FileInputStream inputStream = new FileInputStream(new File(fileName)); 
3、使用ExcelUtils工具类读取 字节流 + 路径。
//通过ExcelUtils工具将Excel数据存入到list中,工具代码下面细讲,这一步读取Excel已经完成了,如果不想进行插入数据库操作,可以直接拿着list用啦。
List<List<Object>> list = ExcelUtils.getListByExcel(inputStream,fileName); 
4、ExcelUtils工具类对数据进行处理,因为表格有行和列,所以处理完数据使用二维集合List<List>对数据进行存储。
ExcelUtils类讲解:
public class ExcelUtils {private final static String excel2003L =".xls";    //2003- 版本的excelprivate final static String excel2007U =".xlsx";  //2007版本/*** @Description:获取IO流中的数据,组装成List<List<Object>>对象* @param in,fileName* @return* @throws*/public static List<List<Object>> getListByExcel(InputStream in, String fileName) throws Exception{List<List<Object>> list = null;//创建Excel工作薄Workbook work = getWorkbook(in,fileName);if(null == work){throw new Exception("创建Excel工作薄为空!");}Sheet sheet = null;  //页数Row row = null;  //行数Cell cell = null;  //列数list = new ArrayList<List<Object>>();//遍历Excel中所有的sheetfor (int i = 0; i < work.getNumberOfSheets(); i++) {sheet = work.getSheetAt(i);if(sheet==null){continue;}//遍历当前sheet中的所有行for (int j = sheet.getFirstRowNum(); j <= sheet.getLastRowNum(); j++) {row = sheet.getRow(j);if(row==null){continue;}//遍历所有的列List<Object> li = new ArrayList<Object>();for (int y = row.getFirstCellNum(); y < row.getLastCellNum(); y++) {cell = row.getCell(y);li.add(getValue(cell));}list.add(li);}}return list;}/*** @Description:根据文件后缀,自适应上传文件的版本* @param inStr,fileName* @return* @throws Exception*/public static  Workbook getWorkbook(InputStream inStr,String fileName) throws Exception{Workbook wb = null;String fileType = fileName.substring(fileName.lastIndexOf("."));if(excel2003L.equals(fileType)){wb = new HSSFWorkbook(inStr);  //2003-}else if(excel2007U.equals(fileType)){wb = new XSSFWorkbook(inStr);  //2007+}else{throw new Exception("解析的文件格式有误!");}return wb;}/*** @Description:对表格中数值进行格式化* @param cell* @return*///解决excel类型问题,获得数值public static String getValue(Cell cell) {String value = "";if(null==cell){return value;}switch (cell.getCellType()) {//数值型case NUMERIC:if (DateUtil.isCellDateFormatted(cell)) {//如果是date类型则 ,获取该cell的date值Date date = DateUtil.getJavaDate(cell.getNumericCellValue());SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");value = format.format(date);;}else {// 纯数字BigDecimal big=new BigDecimal(cell.getNumericCellValue());value = big.toString();//解决1234.0  去掉后面的.0if(null!=value&&!"".equals(value.trim())){String[] item = value.split("[.]");if(1<item.length&&"0".equals(item[1])){value=item[0];}}}break;//字符串类型case STRING:value = cell.getStringCellValue();break;// 公式类型case FORMULA://读公式计算值value = String.valueOf(cell.getNumericCellValue());if (value.equals("NaN")) {// 如果获取的数据值为非法值,则转换为获取字符串value = cell.getStringCellValue();}break;// 布尔类型case BOOLEAN:value = " "+ cell.getBooleanCellValue();break;default:value = cell.getStringCellValue();}if("null".endsWith(value.trim())){value="";}return value;}
} 
5、已经获取到了Excel表格中所有的数据,包含所有的行和列,都在List<List>中,这一步所有的数据获取完了
6、有了数据,要将数据存储到数据库。
7、需要创建数据库字段的实体类,使用@Excel注解将表格和数据库字段名一一对应
@Data
@TableName("t_student")//数据库名字
public class Student{@TableId(type = IdType.AUTO)@Excel(name = "序号", cellType = Excel.ColumnType.NUMERIC)private Long id;@Excel(name = "学生ID")private Long id;@Excel(name = "名称")private String name;@Excel(name = "性别")private String sex;@Excel(name = "年龄")private String age;} 
8、通过双重 for循环遍历List<List>,内层List为列,外层List为行,如下图将第一行数据单独拿出来,作为判断字段,如果实体类等@Excel注解属性和Excel表格第一行名字相同,对实体类进行set赋值
//定义Excel第一行的属性
List<Object> firstRows = null;
//获取第一行属性 放入firstRows中。
if(list != null && list.size() > 0){firstRows = list.get(0);
}
//遍历除第一行以外的Excel表格中的值
for (int i = 1; i < list.size(); i++) {//rows是某一行,i = 1 为第二行,	i = 2 为第三行List<Object> rows = list.get(i);//数据库数据的实体类Student student =new student();//遍历这一行所有的值for (int j = 0; j < rows.size(); j++){//某一行的某一列 j为列的坐标    String cellVal = (String) rows.get(j);//对实体类进行赋值,使用setFieldValueByFieldName方法,下面详细讲代码TestExcel.setFieldValueByFieldName(questionBank, firstRows.get(j).toString().trim(), 	 cellVal);}}// 使用spring插入到数据库questionBankService.save(questionBank);} 
 
9、从第二行开始,每遍历完一行,将获得一个实体类对象,因为是结合数据库写的实体类,通过springboot可以直接插入数据库。
public class TestExcel {/*** 用反射方法,获取列名,比较,为属性赋值* @param object* @param fieldName* @param val*/public static void setFieldValueByFieldName(Object object, String fieldName, Object val) {try {//通过反射获取所有实体类所有定义的方法,object为数据库实体类Field[] fields = object.getClass().getDeclaredFields();//遍历fieldsfor (int i = 0; i < fields.length; i++) {Field field = fields[i];//读取注释,如@Excel(name = "科目")Excel annotation = field.getAnnotation(Excel.class);//因为private类型,所有要设置允许field.setAccessible(true);//annotation.name() 注解里的属性,如果annotation没写注解,读取原始名字如subjectif(annotation == null){if(fieldName.equals(field.getName())){if(field.getType() == Integer.class){field.set(object, Integer.valueOf(val.toString()));}else if(field.getType() == Long.class){field.set(object, Long.valueOf(val.toString()));}else {field.set(object, val);}return;}  }else {//设置了注解,并且表格里的Excel字段值和注解的name值相同,则为相应字段赋值if(fieldName.equals(annotation.name())){//进行类型判断,因为实体类中变量类型不同。if(field.getType() == Integer.class){field.set(object, Integer.valueOf(val.toString()));}else if(field.getType() == Long.class){field.set(object, Long.valueOf(val.toString()));}else {field.set(object, val);}return;}}}}catch (Exception e){e.printStackTrace();}}} 
六、通用读取excel工具类
package com.ssm;import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;public class ReadExcel {public List<Map<String,String>> readExcel(String filepath, String filename, int startrow, int startcol, int sheetnum) {List<Map<String, String>> varList = new ArrayList<Map<String, String>>();String suffix = filename.substring(filename.lastIndexOf(".") + 1);if ("xls".equals(suffix)) {varList = readExcel2003(filepath, filename, startrow, startcol, sheetnum);} else if ("xlsx".equals(suffix)) {varList = readExcel2007(filepath, filename, startrow, startcol, sheetnum);} else {System.out.println("Only excel files with XLS or XLSX suffixes are allowed to be read!");return null;}return varList;}/*** 读取2003Excel* * @param filepath 文件路径* @param filename 文件名,包括扩展名* @param startrow 开始行号,索引从0开始* @param startcol 开始列号,索引从0开始* @param sheetnum 工作簿,索引从0开始* @return*/public static List<Map<String,String>> readExcel2003(String filepath, String filename, int startrow, int startcol, int sheetnum) {List<Map<String, String>> varList = new ArrayList<Map<String, String>>();try {File target = new File(filepath, filename);FileInputStream fis = new FileInputStream(target);HSSFWorkbook wb = new HSSFWorkbook(fis);fis.close();// sheet 从0开始HSSFSheet sheet = wb.getSheetAt(sheetnum);// 取得最后一行的行号int rowNum = sheet.getLastRowNum() + 1;HSSFRow rowTitle = sheet.getRow(0);// 标题行的最后一个单元格位置int cellTitleNum = rowTitle.getLastCellNum();String[] title = new String[cellTitleNum];for (int i = startcol; i < cellTitleNum; i++) {HSSFCell cell = rowTitle.getCell(Short.parseShort(i + ""));if (cell != null) {cell.setCellType(CellType.STRING);title[i] = cell.getStringCellValue();} else {title[i] = "";}}// 行循环开始for (int i = startrow + 1; i < rowNum; i++) {Map<String, String> varpd = new HashMap<String, String>();// 行HSSFRow row = sheet.getRow(i);// 列循环开始for (int j = startcol; j < cellTitleNum; j++) {HSSFCell cell = row.getCell(Short.parseShort(j + ""));String cellValue = "";if (cell != null) {// 把类型先设置为字符串类型cell.setCellType(CellType.STRING);cellValue = cell.getStringCellValue();}varpd.put(title[j], cellValue);}varList.add(varpd);}wb.close();} catch (Exception e) {System.out.println(e);}return varList;}/*** 读取2007Excel* * @param filepath 文件路径* @param filename 文件名,包括扩展名* @param startrow 开始行号,索引从0开始* @param startcol 开始列号,索引从0开始* @param sheetnum 工作簿,索引从0开始* @return*/public List<Map<String,String>> readExcel2007(String filepath, String filename, int startrow, int startcol, int sheetnum) {List<Map<String, String>> varList = new ArrayList<Map<String, String>>();try {File target = new File(filepath, filename);InputStream ins = new FileInputStream(target);XSSFWorkbook wb = new XSSFWorkbook(ins);ins.close();// 得到Excel工作表对象XSSFSheet sheet = wb.getSheetAt(sheetnum);// 取得最后一行的行号int rowNum = sheet.getLastRowNum() + 1;XSSFRow rowTitle = sheet.getRow(0);int cellTitleNum = rowTitle.getLastCellNum();String[] title = new String[cellTitleNum];for (int i = startcol; i < cellTitleNum; i++) {XSSFCell cell = rowTitle.getCell(Short.parseShort(i + ""));if (cell != null) {// 把类型先设置为字符串类型cell.setCellType(CellType.STRING);title[i] = cell.getStringCellValue();} else {title[i] = "";}}// 行循环开始for (int i = startrow + 1; i < rowNum; i++) {Map<String, String> varpd = new HashMap<String, String>();// 得到Excel工作表的行XSSFRow row = sheet.getRow(i);// 列循环开始for (int j = startcol; j < cellTitleNum; j++) {// 得到Excel工作表指定行的单元格XSSFCell cell = row.getCell(j);String cellValue = "";if (cell != null) {// 把类型先设置为字符串类型cell.setCellType(CellType.STRING);cellValue = cell.getStringCellValue();}varpd.put(title[j], cellValue);}varList.add(varpd);}wb.close();} catch (Exception e) {System.out.println(e);}return varList;}} 
相关文章:
Java 读取excel文件
导入: 先导入依赖: <!-- 文件上传 --> <dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpmime</artifactId><version>4.5.7</version> </dependency> <!-- JSON -…...
PageRank(上):数据分析 | 数据挖掘 | 十大算法之一
⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ 🐴作者:秋无之地 🐴简介:CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作,主要擅长领域有:爬虫、后端、大数据开发、数据分析等。 🐴欢迎小伙伴们点赞👍🏻、收藏⭐️、…...
吃鸡达人专享!提高战斗力,分享干货,查询装备皮肤,保护账号安全!
大家好!作为专业吃鸡行家,我将为您带来一些热门话题和实用内容,帮助您提升游戏战斗力,分享顶级游戏作战干货,并提供便捷的作图工具和查询服务。让我们一起享受吃鸡的乐趣! 首先,我要推荐一款绝地…...
力扣第101题 c++ 递归 迭代 双方法 +注释 ~
题目 101. 对称二叉树 简单 给你一个二叉树的根节点 root , 检查它是否轴对称。 示例 1: 输入:root [1,2,2,3,4,4,3] 输出:true示例 2: 输入:root [1,2,2,null,3,null,3] 输出:false提示&a…...
Go:实现SMTP邮件发送订阅功能(包含163邮箱、163企业邮箱、谷歌gmail邮箱)
需求很简单,就是用户输入自己的邮箱后,使用官方邮箱给用户发送替邮件模版 目录 前置邮件模版邮箱开启SMTP服务163邮箱163企业邮箱谷歌gmail邮箱腾讯企业邮箱-失败其他邮箱-未操作 邮件发送核心代码config.yaml配置读取邮件相关配置发送邮件 附录 前置 邮…...
Scala第十六章节
Scala第十六章节 scala总目录 文档资料下载 章节目标 掌握泛型方法, 类, 特质的用法了解泛型上下界相关内容了解协变, 逆变, 非变的用法掌握列表去重排序案例 1. 泛型 泛型的意思是泛指某种具体的数据类型, 在Scala中, 泛型用[数据类型]表示. 在实际开发中, 泛型一般是结合…...
C语言 实现 链 显示 效果 查找 修改 删除
显示所有信息 2023年10月1日的描述:今天放假 2023年10月2日的描述:今天有体育 2023年10月3日的描述:今天有数学 2023年10月4日的描述:今天有语文 2023年10月5日的描述:今天有政治 2023年10月6日的描述:今天交学费 2023年10月7日的描述:今天周末 2023年10月8日的描述:今天给家里…...
CSS基础语法第一天
目录 一、CSS 简介 1.1 CSS简介 1.2 CSS语法 1.3 CSS 语法规范 1.4 CSS 代码风格 1.4.1 样式格式书写 1.4.2 样式大小写 1.4.3 空格规范 二、CSS 基础选择器 2.1选择器分类 2.2标签选择器 2.3 类选择器 2.4 id选择器 2.5 通配符选择器 三、盒子尺寸和背景色 …...
Leetcode 1492.n的第k个因子
给你两个正整数 n 和 k 。 如果正整数 i 满足 n % i 0 ,那么我们就说正整数 i 是整数 n 的因子。 考虑整数 n 的所有因子,将它们 升序排列 。请你返回第 k 个因子。如果 n 的因子数少于 k ,请你返回 -1 。 示例 1: 输入&#…...
十一工具箱流量主小程序源码
无授权,去过滤机制版本 看到网上发布的都是要授权的 朋友叫我把他去授权,能用就行 就把过滤去了 这样就不用授权 可以免费使用 白嫖党专属 一切接口可用,无需担心不能用 授权者不关站一直可以用 源码下载:https://download.csdn.…...
10.5汇编语言整理
【汇编语言相关语法】 1.汇编语言的组成部分 1.伪操作:不参与程序的执行,但是用于告诉编译器程序该怎么编译 .text .global .end .if .else .endif .data 2.汇编指令 编译器将一条汇编指令编译成一条机器码,在内存里一条指令占4字节内存&…...
Connect to 127.0.0.1:1080 [/127.0.0.1] failed: Connection refused: connect
报错信息 A problem occurred configuring root project CourseSelection. > Could not resolve all artifacts for configuration :classpath.> Could not resolve com.android.tools.build:gradle:3.6.1.Required by:project :> Could not resolve com.android.tool…...
驱动器类产品的接口EMC拓扑方案
驱动器类产品的接口EMC拓扑方案 1. 概述 本文以高压伺服驱动器和变频器类产品为例,对常用端口滤波拓扑方案进行总结,后续根据不同的应用场景可进行适当删减,希望对大家有帮助。 2. 驱动器验证等级 本文推荐拓扑的实验结果,满足…...
2023最新ICP备案查询系统源码 附教程 Thinkphp框架
2023最新ICP备案查询系统源码 附教程 thinkphp框架 本系统支持网址备案,小程序备案,APP备案查询,快应用备案查询 优势: 响应速度快,没有延迟,没有缓存,数据与官方同步 源码下载:ht…...
大数据Doris(六):编译 Doris遇到的问题
文章目录 编译 Doris遇到的问题 一、js_generator.cc:(.text+0xfc3c): undefined reference to `well_known_types_js’...
vue重修004上部
文章目录 版权声明组件的三大组成部分scoped解决样式冲突scoped原理2.代码演示 组件data函数说明演示 组件通信组件关系分类通信解决方案父子通信流程子向父通信代 props详解props校验props&data、单向数据流 小黑记事本(组件版)基础组件结构需求和实…...
【C++ techniques】要求/禁止/判断—对象产生于堆中
有时候我们想让某种对象具有“自杀”的能力,所以我们必须要求对象存在堆中,以便我们调用delete this;另一些时候,我们要求拥有某种确定性,保证某一些类型绝不会发生内存泄漏,原因是没有任何一个该类型的对象…...
吃鸡高手亲授:玩转绝地求生,分享顶级游戏干货!
绝地求生(PUBG)自上线以来,成为了全球热门游戏。作为吃鸡行家,我将分享一些独家技巧和干货,帮助您提高游戏战斗力,享受顶级游戏作战体验! 首先,让我们谈一谈战斗力升级。想要在吃鸡游…...
Vue中如何进行自定义图表与可视化图形设计
Vue中如何进行自定义图表与可视化图形设计 在现代Web应用程序开发中,数据可视化图表和图形设计是至关重要的一部分。Vue.js是一个流行的JavaScript框架,它提供了强大的工具来构建交互性强大的用户界面。本文将探讨如何在Vue.js中进行自定义图表和可视化…...
学信息系统项目管理师第4版系列19_质量管理
1. 公差 1.1. 质量测量中公差是测量指标的可允许变动范围,而不是实际测量值与预期值的差 1.1.1. 【高22下选35】 1.2. 结果的的可接受范围 2. 控制界限 2.1. 统计意义上稳定的过程或过程绩效的普通偏差的边界 3. 3版 3.1. 质量控制新七工具 3.1.1. 【高19下…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
