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下…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
c++第七天 继承与派生2
这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分:派生类构造函数与析构函数 当创建一个派生类对象时,基类成员是如何初始化的? 1.当派生类对象创建的时候,基类成员的初始化顺序 …...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...
人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent
安全大模型训练计划:基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标:为安全大模型创建高质量、去偏、符合伦理的训练数据集,涵盖安全相关任务(如有害内容检测、隐私保护、道德推理等)。 1.1 数据收集 描…...
redis和redission的区别
Redis 和 Redisson 是两个密切相关但又本质不同的技术,它们扮演着完全不同的角色: Redis: 内存数据库/数据结构存储 本质: 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能: 提供丰…...
Python常用模块:time、os、shutil与flask初探
一、Flask初探 & PyCharm终端配置 目的: 快速搭建小型Web服务器以提供数据。 工具: 第三方Web框架 Flask (需 pip install flask 安装)。 安装 Flask: 建议: 使用 PyCharm 内置的 Terminal (模拟命令行) 进行安装,避免频繁切换。 PyCharm Terminal 配置建议: 打开 Py…...
SQL进阶之旅 Day 22:批处理与游标优化
【SQL进阶之旅 Day 22】批处理与游标优化 文章简述(300字左右) 在数据库开发中,面对大量数据的处理任务时,单条SQL语句往往无法满足性能需求。本篇文章聚焦“批处理与游标优化”,深入探讨如何通过批量操作和游标技术提…...
MLP实战二:MLP 实现图像数字多分类
任务 实战(二):MLP 实现图像多分类 基于 mnist 数据集,建立 mlp 模型,实现 0-9 数字的十分类 task: 1、实现 mnist 数据载入,可视化图形数字; 2、完成数据预处理:图像数据维度转换与…...
