当前位置: 首页 > news >正文

读取Excel的工具类——ExcelKit

文章目录

  • ExcelKit工具类
    • 1、准备工作
      • 1.1、SheetInfoVo
      • 1.2、BizException
    • 2、读取xlsx
    • 3、读取xls
    • 4、完整的ExcelKit.java源码

ExcelKit工具类

1、准备工作

1.1、SheetInfoVo

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;@Data
@AllArgsConstructor
@NoArgsConstructor
public class SheetInfoVo implements Serializable {/***  读取的sheet页*/private int sheetIndex;/***  忽略的行数*/private int ignoreRow;/***  忽略的列数*/private int ignoreColumn;/***  指定行(如果不指定,那么动态获取)*/private int lastRowNum;/***  指定列(如果不指定,那么动态获取)*/private int lastCellNum;}

1.2、BizException

/*** 业务性异常类*/
public class BizException extends RuntimeException{/** 数据校验异常 */public static final String ERRORCODE_INVALID_DATA = "01";/** 当前用户没有操作权限 */public static final String ERRORCODE_UNAUTHORIZED = "02";/** 数据当前状态不允许该操作 */public static final String ERRORCODE_INVALID_STATUS = "03";/** 其他业务异常 */public static final String ERRORCODE_OTHER = "99";private final String errorCode;public BizException(String errorCode, String message) {super(message);this.errorCode = errorCode;}public BizException(String errorCode, String message, Throwable cause) {super(message, cause);this.errorCode = errorCode;}public String getErrorCode() {return errorCode;}
}

2、读取xlsx

依赖包:

<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.2</version>
</dependency>

读取方法:

/**
* 读取xlsx文件的第一个Sheet页(07)
* @param inputStream
* @return
*/
public static List<List<String>> readOneXlsxSheet(final FileInputStream inputStream, final SheetInfoVo sheetInfo) throws BizException {List<List<String>> resultList = new LinkedList<>();SheetInfoVo vo = initSheetInfo(sheetInfo);int sheetIndex = vo.getSheetIndex();int ignoreRow = vo.getIgnoreRow();int ignoreColumn = vo.getIgnoreColumn();int lastRowNum = vo.getLastRowNum();int lastColumnNum = vo.getLastCellNum();try {//poi-ooxml包XSSFWorkbook workbook= new XSSFWorkbook(inputStream);Sheet sheet = workbook.getSheetAt(sheetIndex);//如果有指定读取到第几行,那么按指定的来lastRowNum = lastRowNum == 0 ? sheet.getLastRowNum() : lastRowNum;for (int rowIndex = ignoreRow; rowIndex <= lastRowNum; rowIndex++) {Row row = sheet.getRow(rowIndex);if (row == null) {continue;}int lastCellNum = lastColumnNum == 0 ? row.getLastCellNum() : lastColumnNum;List<String> result = new LinkedList<>();for (int columnIndex = ignoreColumn; columnIndex < lastCellNum; columnIndex++) {Cell cell = row.getCell(columnIndex);String value = getCellValue(cell);result.add(value);}resultList.add(result);}}catch (IllegalArgumentException e) {throw new BizException(BizException.ERRORCODE_INVALID_STATUS, "读取的sheet页异常或读取的单元格异常,请联系IT处理");}catch (Exception e) {throw new BizException(BizException.ERRORCODE_INVALID_STATUS, "文件读取异常,请联系IT处理");}return resultList;
}

3、读取xls

依赖包:

<dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.2</version>
</dependency>

读取文件方法:

/**
* 读取xls文件的第一个Sheet页(03)
* @param inputStream
* @return
*/
public static List<List<String>> readOneXlsSheet(FileInputStream inputStream, SheetInfoVo sheetInfo) throws BizException{List<List<String>> resultList = new LinkedList<>();SheetInfoVo vo = initSheetInfo(sheetInfo);int sheetIndex = vo.getSheetIndex();int ignoreRow = vo.getIgnoreRow();int ignoreColumn = vo.getIgnoreColumn();int lastRowNum = vo.getLastRowNum();int lastColumnNum = vo.getLastCellNum();try {//poi-ooxml包Workbook workbook= new HSSFWorkbook(inputStream);Sheet sheet = workbook.getSheetAt(sheetIndex);//如果有指定读取到第几行,那么按指定的来lastRowNum = lastRowNum == 0 ? sheet.getLastRowNum() : lastRowNum;for (int rowIndex = ignoreRow; rowIndex <= lastRowNum; rowIndex++) {Row row = sheet.getRow(rowIndex);if (row == null) {continue;}int lastCellNum = lastColumnNum == 0 ? row.getLastCellNum() : lastColumnNum;List<String> result = new LinkedList<>();for (int columnIndex = ignoreColumn; columnIndex < lastCellNum; columnIndex++) {Cell cell = row.getCell(columnIndex);String value = getCellValue(cell);result.add(value);}resultList.add(result);}}catch (IllegalArgumentException e) {throw new BizException(BizException.ERRORCODE_INVALID_STATUS, "读取的sheet页异常或读取的单元格异常,请联系IT处理");}catch (Exception e) {throw new BizException(BizException.ERRORCODE_INVALID_STATUS, "文件读取异常,请联系IT处理");}return resultList;
}

4、完整的ExcelKit.java源码

使用的时候切记要把包名导入,并修改导入的 BizException 和 SheetInfoVo 类路径。

使用的时候切记要把包名导入,并修改导入的 BizException 和 SheetInfoVo 类路径。

使用的时候切记要把包名导入,并修改导入的 BizException 和 SheetInfoVo 类路径。

package com.example.kit;import com.example.common.BizException;
import com.example.vo.SheetInfoVo;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.regex.Pattern;public class ExcelKit {/*** 读取Excel文件,默认读取第一个Sheet页,不跳过所有行与列* @param file* @return* @throws Exception*/public static List<List<String>> readOneSheet(File file) throws Exception {return readOneSheet(file, null);}/*** 读取Excel文件,通过sheetInfo对象,指定读取的sheet页、跳过行列标题数,甚至指定读取的行数列数数* @param file          读取的文件* @param sheetInfo     读取的形式* @return              读取到的二维 String 列表* @throws IOException* @throws BizException*/public static List<List<String>> readOneSheet(File file, SheetInfoVo sheetInfo) throws IOException, BizException {if (file == null) {throw new FileNotFoundException("读取文件不能为空!");}FileInputStream inputStream = new FileInputStream(file);String fileName = file.getName();Workbook workbook = null;if (fileName.endsWith(".xls")) {workbook = new HSSFWorkbook(inputStream);}else if (fileName.endsWith(".xlsx")) {workbook = new XSSFWorkbook(inputStream);}else {throw new BizException(BizException.ERRORCODE_INVALID_STATUS, "上传文件类型有误,请上传.xls或.xlsx的文件");}return readOneExcelSheet(workbook, sheetInfo);}public static List<List<String>> readOneExcelSheet(final Workbook workbook, final SheetInfoVo sheetInfo) throws BizException {List<List<String>> resultList = new LinkedList<>();SheetInfoVo vo = initSheetInfo(sheetInfo);int sheetIndex = vo.getSheetIndex();int ignoreRow = vo.getIgnoreRow();int ignoreColumn = vo.getIgnoreColumn();int lastRowNum = vo.getLastRowNum();int lastColumnNum = vo.getLastCellNum();try {Sheet sheet = workbook.getSheetAt(sheetIndex);//如果有指定读取到第几行,那么按指定的来lastRowNum = lastRowNum == 0 ? sheet.getLastRowNum() : lastRowNum;for (int rowIndex = ignoreRow; rowIndex <= lastRowNum; rowIndex++) {Row row = sheet.getRow(rowIndex);if (row == null) {continue;}int lastCellNum = lastColumnNum == 0 ? row.getLastCellNum() : lastColumnNum;List<String> result = new LinkedList<>();for (int columnIndex = ignoreColumn; columnIndex < lastCellNum; columnIndex++) {Cell cell = row.getCell(columnIndex);String value = getCellValue(cell);result.add(value);}resultList.add(result);}}catch (IllegalArgumentException e) {throw new BizException(BizException.ERRORCODE_INVALID_STATUS, "读取的sheet页异常或读取的单元格异常,请联系IT处理");}catch (Exception e) {throw new BizException(BizException.ERRORCODE_INVALID_STATUS, "文件读取异常,请联系IT处理");}return resultList;}/*** 初始化 SheetInfo* @param sheetInfo* @return*/private static SheetInfoVo initSheetInfo(final SheetInfoVo sheetInfo) {SheetInfoVo vo = new SheetInfoVo(0, 0, 0, 0, 0);if (sheetInfo == null) {vo.setSheetIndex(0);vo.setIgnoreRow(0);vo.setIgnoreColumn(0);vo.setLastRowNum(0);vo.setLastCellNum(0);}else {int sheetIndex = sheetInfo.getSheetIndex();int ignoreRow = sheetInfo.getIgnoreRow();int ignoreColumn = sheetInfo.getIgnoreColumn();int lastRowNum = sheetInfo.getLastRowNum();int lastCellNum = sheetInfo.getLastCellNum();if (isNotNullAndBigThenZero(sheetIndex)) {vo.setSheetIndex(sheetIndex);}if (isNotNullAndBigThenZero(ignoreRow)) {vo.setIgnoreRow(ignoreRow);}if (isNotNullAndBigThenZero(ignoreColumn)) {vo.setIgnoreColumn(ignoreColumn);}if (isNotNullAndBigThenZero(lastRowNum)) {vo.setLastRowNum(lastRowNum);}if (isNotNullAndBigThenZero(lastCellNum)) {vo.setLastCellNum(lastCellNum);}}return vo;}private static boolean isNotNullAndBigThenZero(Integer value) {if (value != null && value > 0) {return true;}return false;}/*** 获取单元格数据* @param cell* @return*/private static String getCellValue(Cell cell) {String value = "";if (cell == null) {return value;}switch (cell.getCellType()) {case STRING:value = cell.getRichStringCellValue().getString();break;case NUMERIC:if (DateUtil.isCellDateFormatted(cell)) {Date date = cell.getDateCellValue();if (date != null) {value = new SimpleDateFormat("yyyy-MM-dd").format(date);} else {value = "";}} else {value = getRealStringValueOfDouble(cell.getNumericCellValue());}break;case FORMULA:cell.setCellType(CellType.STRING);// 导入时如果为公式生成的数据则无值if (!cell.getRichStringCellValue().getString().equals("")) {value = cell.getRichStringCellValue().getString();} else {value = cell.getNumericCellValue() + "";}break;case BOOLEAN:value = (cell.getBooleanCellValue() == true ? "Y" : "N");break;default:value = "";break;}return value;}// 处理科学计数法与普通计数法的字符串显示,尽最大努力保持精度private static String getRealStringValueOfDouble(Double value) {String doubleStr = value.toString();//是否使用科学计数法boolean isScientificNotation = doubleStr.contains("E");if (isScientificNotation) {//很小的小数if (doubleStr.contains("E-")) {doubleStr = handleSoSmallNumber(doubleStr);}else { //很大的数doubleStr = handleSoBigNumber(doubleStr);}} else {java.util.regex.Pattern p = Pattern.compile(".0$");java.util.regex.Matcher m = p.matcher(doubleStr);if (m.find()) {doubleStr = doubleStr.replace(".0", "");}}return doubleStr;}/*** 处理科学计数法很小的数,类似0.00000000000000123456* @param value* @return*/private static String handleSoSmallNumber(String value) {StringBuffer sb = new StringBuffer();int indexOfE = value.indexOf("E-");//小数的尾巴String tail = value.substring(0, indexOfE).replace(".", "");//指数int pow = Integer.parseInt(value.substring(indexOfE + 2));//补零sb.append("0.");while (--pow > 0) {sb.append("0");}sb.append(tail);return sb.toString();}/*** 处理科学计数法很大的数,类似12345678910.123456* @param value* @return*/private static String handleSoBigNumber(String value) {StringBuffer sb = new StringBuffer();int indexOfE = value.indexOf("E");int pow = Integer.parseInt(value.substring(indexOfE + 1));int valueLength = value.substring(0, indexOfE).length();if (pow > valueLength - 2) {String head = value.substring(0, indexOfE).replace(".", "");sb.append(head);int zeroNum = pow - head.length() + 1;while (zeroNum-- > 0) {sb.append("0");}}else {String head = value.substring(0, pow + 2).replace(".", "");String tail = value.substring(pow + 2, indexOfE);sb.append(head).append(".").append(tail);}return sb.toString();}
}

相关文章:

读取Excel的工具类——ExcelKit

文章目录 ExcelKit工具类1、准备工作1.1、SheetInfoVo1.2、BizException 2、读取xlsx3、读取xls4、完整的ExcelKit.java源码 ExcelKit工具类 1、准备工作 1.1、SheetInfoVo import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;import …...

vscode连接服务器一直retry

解决方法 打开vscode控制面板&#xff0c;输入命令remote-ssh: kill vs code server on host 选择一直连接不上的服务器端口 重新连接...

Spring Cloud Sentinel整合Nacos实现配置持久化

sentinel配置相关配置后无法持久化&#xff0c;服务重启之后就没了&#xff0c;所以整合nacos&#xff0c;在nacos服务持久化&#xff0c;sentinel实时与nacos通信获取相关配置。 使用上一章节Feign消费者服务实现整合。 版本信息&#xff1a; nacos:1.4.1 Sentinel 控制台 …...

STM32F4VGT6-DISCOVERY:uart1驱动

对于这款板子&#xff0c;官方并没有提供串口例程&#xff0c;只能自行添加。 一、PA9/PA10复用成串口1功能不可用 驱动测试代码如下&#xff1a; main.c: #include "main.h" #include <stdio.h>void usart1_init(void) {GPIO_InitTypeDef GPIO_InitStruct…...

C语言之 结构体,枚举,联合

目录 1.结构体 1.1结构的基础知识 1.2结构的声明 1.3 特殊的声明 1.4 结构的自引用 1.5 结构体变量的定义和初始化 1.6 结构体内存对齐 1.7 修改默认对齐数 1.8 结构体传参 2. 位段 2.1 什么是位段 2.2位段的内存分配 2.3 位段的跨平台问题 3. 枚举 3.1 枚举类型…...

红米电脑硬盘剪切

Redmi R14 2023版固态硬盘剪切 工具准备操作结尾语 首先要说明&#xff0c;本文所说的操作不一定适合你的电脑&#xff0c;因为电子产品更新换代过快&#xff0c;你的硬盘不一定能剪切&#xff0c;在操作前一定要仔细观察硬盘的型号&#xff0c;是否为同款&#xff0c;我上了图…...

微信小程序在线预览PDF文件

需求&#xff1a;微信小程序在线预览PDF合同文件&#xff0c;加载完成后强制阅读10秒才可点击同意按钮 H5代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" cont…...

Android 工厂模式增加Type-A功能测试

Android 工厂模式增加Type-A功能测试 收到客户需求想要增加Type-A测试项来验证Type-A功能&#xff0c;具体功能实现参照如下&#xff1a; /vendor/freeme/packages/apps/FreemeFactoryTest/src/com/freeme/factory/usb/TypeAUSB.java package com.freeme.factory.usb;i…...

Web攻防06_sqlmap的使用

文章目录 参考链接&#xff1a; SQLMAP简介支持五种不同的注入模式 数据猜解-库表列数据权限操作引出权限&#xff1a;引出文件&#xff1a;引出命令&#xff08;执行命令&#xff09;&#xff1a; 提交方法-POST&HEAD&JSONPost注入cookie注入注入请求头中&#xff08;…...

C++模拟实现-----日期计算器(超详细解析,小白一看就会!)

目录 一、前言 二、日期类计算器 三、日期计算器的实现 &#x1f34e;日期计算器各个接口的实现 &#x1f350;日期计算器的需求 &#x1f349;打印当前日期&#xff08;并检查日期是否合理&#xff09; &#x1f4a6;检查日期是否合理 &#x1f4a6;日期类构造函数&#x…...

Oracle实现把B表某一字段更新到A表

1.使用SQL命令UPDATE语句。 2.使用MERGE语句。 3.使用TRIGGER触发器。 4.使用游标CURSOR和循环 使用游标和循环来将B表中的数据更新到A表中&#xff0c;从而实现了两个表数据的同步。例如下面的代码实现&#xff1a;...

CUMCM历年赛题汇总

题目来源&#xff1a; 全国大学生数学建模竞赛官网 注&#xff1a;题目和数据均可在官网下载 2021–2023年 年份题号题目2023A定日镜场的优化设计2023B多波束测线问题2023C蔬菜类商品的自动定价与补货决策2023D圈养湖羊的空间利用率2023E黄河水沙监测数据分析2022A波浪能最大…...

人间道-您到底做错了什么:正心径之您要逐渐去除外邪行为

过去的您或许在您自个身上付出&#xff0c;投入了巨大&#xff0c;重大的人力&#xff0c;物力&#xff0c;财力等各方面的重重的成本&#xff0c;但是呢&#xff0c;收获却微小的稀罕&#xff0c;微少的可怜啊。甚至于一个错误&#xff0c;就把您完全陷入到万丈深渊里面去了&a…...

Spring Boot拓展XML格式的请求和响应

在我们开发过程中&#xff0c;我们经常使用的参数绝大多少事HTML和JSON格式的请求和响应处理&#xff0c;但是我们在实际开发过程中&#xff0c;我们可能经历一些&#xff0c;比如对于XML格式的请求&#xff0c;我们在后端应该如何接收&#xff0c;并且如何将XML格式的参数变成…...

0045【Edabit ★☆☆☆☆☆】【字符数转整型】Return a String as an Integer

0045【Edabit ★☆☆☆☆☆】【字符数转整型】Return a String as an Integer language_fundamentals numbers strings Instructions Create a function that takes a string and returns it as an integer. Examples stringInt("6") // 6 stringInt("1000&q…...

数据库MySQL(六):事务

事务 事务是一组操作的集合&#xff0c;它是一个不可分割的工作单位&#xff0c;事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求&#xff0c;即这些操作要么同时成功&#xff0c;要么同时失败。 MySQL中默认事务是自动提交的&#xff0c;当执行完一条DML语句时…...

比较浮点数时,我被绊倒了

&#x1f4e2;欢迎点赞 &#xff1a;&#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff0c;赐人玫瑰&#xff0c;手留余香&#xff01;&#x1f4e2;本文作者&#xff1a;由webmote 原创&#x1f4e2;作者格言&#xff1a;新的征程&#xff0c;我们面对的不是…...

JVM进阶(1)

一)JVM是如何运行的&#xff1f; 1)在程序运行前先将JAVA代码转化成字节码文件也就是class文件&#xff0c;JVM需要通过类加载器将字节码以一定的方式加载到JVM的内存运行时数据区&#xff0c;将类的信息打包分块填充在运行时数据区&#xff1b; 2)但是字节码文件是JVM的一套指…...

【AICFD案例操作】汽车外气动分析

AICFD是由天洑软件自主研发的通用智能热流体仿真软件&#xff0c;用于高效解决能源动力、船舶海洋、电子设备和车辆运载等领域复杂的流动和传热问题。软件涵盖了从建模、仿真到结果处理完整仿真分析流程&#xff0c;帮助工业企业建立设计、仿真和优化相结合的一体化流程&#x…...

Hadoop 请求数据长度 Requested Data length 超过配置的最大值

一、问题 现象 Spark 任务速度变慢&#xff0c;也不失败。 DataNode 内存足够 CPU 负载不高 GC 时间也不长。 查看 DataNode 日志&#xff0c;发现有些日志出现很多 Netty RPC 超时。超时的 destination 是一个 NameNode 节点&#xff0c;然后查看 NameNode 节点的日志&…...

汽车生产虚拟实训中的技能提升与生产优化​

在制造业蓬勃发展的大背景下&#xff0c;虚拟教学实训宛如一颗璀璨的新星&#xff0c;正发挥着不可或缺且日益凸显的关键作用&#xff0c;源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例&#xff0c;汽车生产线上各类…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

Python爬虫(二):爬虫完整流程

爬虫完整流程详解&#xff08;7大核心步骤实战技巧&#xff09; 一、爬虫完整工作流程 以下是爬虫开发的完整流程&#xff0c;我将结合具体技术点和实战经验展开说明&#xff1a; 1. 目标分析与前期准备 网站技术分析&#xff1a; 使用浏览器开发者工具&#xff08;F12&…...

【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统

目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索&#xff08;基于物理空间 广播范围&#xff09;2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

网站指纹识别

网站指纹识别 网站的最基本组成&#xff1a;服务器&#xff08;操作系统&#xff09;、中间件&#xff08;web容器&#xff09;、脚本语言、数据厍 为什么要了解这些&#xff1f;举个例子&#xff1a;发现了一个文件读取漏洞&#xff0c;我们需要读/etc/passwd&#xff0c;如…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

人工智能 - 在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型

在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型。这些平台各有侧重&#xff0c;适用场景差异显著。下面我将从核心功能定位、典型应用场景、真实体验痛点、选型决策关键点进行拆解&#xff0c;并提供具体场景下的推荐方案。 一、核心功能定位速览 平台核心定位技术栈亮…...

Java设计模式:责任链模式

一、什么是责任链模式&#xff1f; 责任链模式&#xff08;Chain of Responsibility Pattern&#xff09; 是一种 行为型设计模式&#xff0c;它通过将请求沿着一条处理链传递&#xff0c;直到某个对象处理它为止。这种模式的核心思想是 解耦请求的发送者和接收者&#xff0c;…...

LeetCode 0386.字典序排数:细心总结条件

【LetMeFly】386.字典序排数&#xff1a;细心总结条件 力扣题目链接&#xff1a;https://leetcode.cn/problems/lexicographical-numbers/ 给你一个整数 n &#xff0c;按字典序返回范围 [1, n] 内所有整数。 你必须设计一个时间复杂度为 O(n) 且使用 O(1) 额外空间的算法。…...