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下…...

SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...

MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...

1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...

高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...