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下…...
大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...
Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...
