JAVA读写Excel(jxl,poi,easyExcel)

目录

一、需求描述

二、具体操作Excel的常用方法

方法一: 使用jxl

方法二: POI

方法三:EasyExcel

三、总结


一、需求描述

前端有时候会传送 Excel 文件给后端(Java)去解析,那我们作为后端该如何实现对 Excel 文件的解析和数据读取呢?

使用Java对Excel文件进行读写,文件后缀可能为.xls, .xlsx

二、具体操作Excel的常用方法

方法一: 使用jxl

JXL:  开源库,支持.xls文件(EXCEL 2003格式)的读写

注意: JXL不支持.xlsx文件(EXCEL 2007格式)的读写

使用:

1. pom.xml文件引入 <!--读取excel文件--><!-- https://mvnrepository.com/artifact/net.sourceforge.jexcelapi/jxl --><dependency><groupId>net.sourceforge.jexcelapi</groupId><artifactId>jxl</artifactId><version>2.6.12</version></dependency>2. jxl读文件import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import jxl.write.WriteException;import java.io.File;
import java.io.IOException;
import java.util.ArrayList;//读文件/*** 返回上传的Excel表格的内容* Jxl是一款常用的Java中操作Excel的API,但其只对xls有效,对2007版本以上的Excel(xlsx)很难处理。*/public static List<String[]> parseExcel(String filePath) throws Exception {List<String[]> list = new ArrayList<>();Workbook wb = Workbook.getWorkbook(new File(filePath));Sheet sheet = wb.getSheets()[0];int columns = sheet.getRow(0).length;for (int i = 0; i < sheet.getRows(); i++) {String[] line = new String[columns];for (int j = 0; j < columns; j++) {Cell cell = sheet.getCell(j, i);String content = null;if (cell != null) {content = cell.getContents();}if (content != null && content.trim().length() == 0) {content = "";}line[j] = content;}list.add(line);}return list;}// 写文件public static void write2File(String filePath, List<GradeVo> gradeVoList) throws IOException, WriteException {// 写入文件File file = new File(filePath);// 创建工作簿WritableWorkbook workbook = Workbook.createWorkbook(file);// 创建工作表WritableSheet sheet = workbook.createSheet("Sheet1", 0);AtomicInteger rowIndex = new AtomicInteger(1);try {//写表头Label label0 = new Label(0, 0, "学号");sheet.addCell(label0);label0 = new Label(1, 0, "姓名");sheet.addCell(label0);label0 = new Label(2, 0, "班级");sheet.addCell(label0);label0 = new Label(3, 0, "每次作业分");sheet.addCell(label0);label0 = new Label(4, 0, "作业平均分");sheet.addCell(label0);label0 = new Label(5, 0, "考勤次数");sheet.addCell(label0);label0 = new Label(6, 0, "回答问题次数");sheet.addCell(label0);label0 = new Label(7, 0, "期末分数");sheet.addCell(label0);label0 = new Label(8, 0, "最终分");sheet.addCell(label0);// 创建单元格并写入数据for (GradeVo value : gradeVoList) {Label label = new Label(0, rowIndex.get(), value.getSNo());sheet.addCell(label);label = new Label(1, rowIndex.get(), value.getSName());sheet.addCell(label);label = new Label(2, rowIndex.get(), value.getSClass());sheet.addCell(label);label = new Label(3, rowIndex.get(), JSON.toJSONString(value.getGrade()));sheet.addCell(label);label = new Label(4, rowIndex.get(), value.getAvgScore() + "");sheet.addCell(label);label = new Label(5, rowIndex.get(), value.getSignInTimes() + "");sheet.addCell(label);label = new Label(6, rowIndex.get(), value.getAnswerTimes() + "");sheet.addCell(label);label = new Label(7, rowIndex.get(), value.getFinalScore() + "");sheet.addCell(label);label = new Label(8, rowIndex.get(), value.getTotalScore() + "");sheet.addCell(label);rowIndex.addAndGet(1);}// 写入数据workbook.write();// 关闭工作簿workbook.close();}catch (WriteException e) {throw new RuntimeException(e);}}

更多用法:

//单元格合并
sheet.mergeCells(0,2,0,3); //把第 0 列第 2 行的单元格和第 0 列第 3 行的单元格合并//设置单元格列宽和行高
sheet.setColumnView(0,10);//设置第 0 列的宽为10
sheet.setRowView(0,1000);//设置第 0 行的高为10//插入字符串数据可用String[]数组(注意需要在下面遍历数组!)
String[] str = {"1","2"};//设置单元格内容样式                           设置字体              字体大小   是否加粗
WritableFont font=new WritableFont(WritableFont.createFont("宋体"),12,WritableFont.BOLD);
WritableCellFormat format = new WritableCellFormat(font);
//水平居中
format.setAlignment(jxl.format.Alignment.CENTRE);

方法二: POI

POI (Poor Obfuscation Implementation)主要是指 Apache提供的操作Office的基础工具包(Apache POI),Apache POI 是一个底层的工具类,可实现的功能最全。

缺点:

解析文件时一次性全部加载到内存中,系统并发量不大时可行,一旦并发上来后会产生OOM或者JVM频繁的full gc

操作:

pom文件引入:

引入 Apache POI 和 Apache POI-OOXML 这两个类库,Maven坐标如下:

<!-- Apache POI -->
<dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>5.2.3</version>
</dependency>
<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.2.3</version>
</dependency>
注意:使用HSSF操作.xls格式文件,使用XSSF操作.xlsx文件 读文件:private final static String xls = "xls";private final static String xlsx = "xlsx";/*** 读入excel文件,解析后返回* @param file* @throws IOException*/public static List<String[]> readExcel(MultipartFile file) throws IOException {//检查文件checkFile(file);//获得Workbook工作薄对象Workbook workbook = getWorkBook(file);//创建返回对象,把每行中的值作为一个数组,所有行作为一个集合返回List<String[]> list = new ArrayList<String[]>();if(workbook != null){for(int sheetNum = 0;sheetNum < workbook.getNumberOfSheets();sheetNum++){//获得当前sheet工作表Sheet sheet = workbook.getSheetAt(sheetNum);if(sheet == null){continue;}//获得当前sheet的开始行int firstRowNum  = sheet.getFirstRowNum();//获得当前sheet的结束行int lastRowNum = sheet.getLastRowNum();//循环除了第一行的所有行for(int rowNum = firstRowNum+1;rowNum <= lastRowNum;rowNum++){ //为了过滤到第一行因为我的第一行是数据库的列//获得当前行Row row = sheet.getRow(rowNum);if(row == null){continue;}//获得当前行的开始列int firstCellNum = row.getFirstCellNum();//获得当前行的列数int lastCellNum = row.getLastCellNum();//为空列获取
//                    int lastCellNum = row.getPhysicalNumberOfCells();//为空列不获取
//                    String[] cells = new String[row.getPhysicalNumberOfCells()];String[] cells = new String[row.getLastCellNum()];//循环当前行for(int cellNum = firstCellNum; cellNum < lastCellNum;cellNum++){Cell cell = row.getCell(cellNum);cells[cellNum] = getCellValue(cell);}list.add(cells);}}}logger.info(gson.toJson(list));return list;}public static void checkFile(MultipartFile file) throws IOException{//判断文件是否存在if(null == file){throw new FileNotFoundException("文件不存在!");}//获得文件名String fileName = file.getOriginalFilename();//判断文件是否是excel文件if(!fileName.endsWith(xls) && !fileName.endsWith(xlsx)){throw new IOException(fileName + "不是excel文件");}}public static Workbook getWorkBook(MultipartFile file) {//获得文件名String fileName = file.getOriginalFilename();//创建Workbook工作薄对象,表示整个excelWorkbook workbook = null;try {//获取excel文件的io流InputStream is = file.getInputStream();//根据文件后缀名不同(xls和xlsx)获得不同的Workbook实现类对象if(fileName.endsWith(xls)){//2003workbook = new HSSFWorkbook(is);}else if(fileName.endsWith(xlsx)){//2007workbook = new XSSFWorkbook(is);}} catch (IOException e) {logger.info(e.getMessage());}return workbook;}public static String getCellValue(Cell cell){String cellValue = "";if(cell == null){return cellValue;}//把数字当成String来读,避免出现1读成1.0的情况if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){cell.setCellType(Cell.CELL_TYPE_STRING);}//判断数据的类型switch (cell.getCellType()){case Cell.CELL_TYPE_NUMERIC: //数字cellValue = String.valueOf(cell.getNumericCellValue());break;case Cell.CELL_TYPE_STRING: //字符串cellValue = String.valueOf(cell.getStringCellValue());break;case Cell.CELL_TYPE_BOOLEAN: //BooleancellValue = String.valueOf(cell.getBooleanCellValue());break;case Cell.CELL_TYPE_FORMULA: //公式
//                cellValue = String.valueOf(cell.getCellFormula());cellValue = String.valueOf(cell.getStringCellValue());break;case Cell.CELL_TYPE_BLANK: //空值cellValue = "";break;case Cell.CELL_TYPE_ERROR: //故障cellValue = "非法字符";break;default:cellValue = "未知类型";break;}return cellValue;}

官网文档:

Busy Developers' Guide to HSSF and XSSF Features

  • 工作簿对象支持设置一些全局性质的对象,例如:
  1.  单元格样式的对象。一个工作簿最多支持6w个单元格的样式;
  2.  创建字体样式的对象。一个工作簿最多支持32767个 字体样式;
  • 工作表对象支持只在单个工作表生效的设置,例如:
  1. 设置筛选按钮; 
  2. 设置某列的自适应列宽;
  3. 冻结窗格;
  4. 拆分窗口;
  • 行对象

Row 支持的操作有:

  1. 创建单元格
  2. 获取/遍历单元格
  3. 设置行高
  4. 获取行号
  5. 设置/隐藏行
  • 单元格对象

单元格对象支持对单个单元格进行设置,例如:

  1. 获取/设置单元格的值
  2. 获取/设置单元格的类型(字符串、数值[数字/日期]、布尔值、公式、错误值、空)
  3. 获取/设置单元格的样式
  4. 获取/设置超链接
  • 单元格的值

    单元格的值有7种类型[CellType](数值、字符串、公式、空值、布尔值、错误值)

方法三:EasyExcel

优点:

Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。
        easyexcel重写了poi对07版Excel的解析,一个3M的excel用POI sax解析依然需要100M左右内存,改用easyexcel可以降低到几M,并且再大的excel也不会出现内存溢出;03版依赖POI的sax模式,在上层做了模型转换的封装,让使用者更加简单方便

操作:

pom文件:

读Excel:DEMO代码地址:https://github.com/alibaba/easyexcel/blob/master/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/demo/read/ReadTest.java
/*** 最简单的读* <p>1. 创建excel对应的实体对象 参照{@link DemoData}* <p>2. 由于默认一行行的读取excel,所以需要创建excel一行一行的回调监听器,参照{@link DemoDataListener}* <p>3. 直接读即可*/@Testpublic void simpleRead() {String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx";// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead();}写Excel:DEMO代码地址:https://github.com/alibaba/easyexcel/blob/master/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/demo/write/WriteTest.java
/*** 最简单的写* <p>1. 创建excel对应的实体对象 参照{@link com.alibaba.easyexcel.test.demo.write.DemoData}* <p>2. 直接写即可*/@Testpublic void simpleWrite() {String fileName = TestFileUtil.getPath() + "write" + System.currentTimeMillis() + ".xlsx";// 这里 需要指定写用哪个class去读,然后写到第一个sheet,名字为模板 然后文件流会自动关闭// 如果这里想使用03 则 传入excelType参数即可EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());}

官网文档:

https://easyexcel.opensource.alibaba.com/docs/current/EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目,在尽可能节约内存的情况下支持读写百M的Excel。icon-default.png?t=N7T8https://easyexcel.opensource.alibaba.com/docs/current/读Excel | Easy Excel 官网

三、总结

  • 如果操作Excel复杂度高(.xls,.xlsx都存在,且内容格式复杂),建议使用POI。
  • 如果操作Excel数据量大并且对对性能有要求,可以使用EasyExcel。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/418880.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Jenkins+Svn+Vue自动化构建部署前端项目(保姆级图文教程)

目录 介绍 准备工作 配置jenkins 构建部署任务 常见问题 介绍 在平常开发前端vue项目时,我们通常需要将vue项目进行打包构建,将打包好的dist目录下的静态文件上传到服务器上,但是这种繁琐的操作是比较浪费时间的,可以使用jenkins进行自动化构建部署前端vue 准备工作 准备…

AI模型的未来之路:全能与专精的博弈与共生

人工智能(AI)领域正迅速发展,伴随着技术的不断进步,AI模型的应用范围也在不断扩展。当前,AI模型的设计和使用面临两个主要趋势:全能型模型和专精型模型。这两者之间的博弈与共生将塑造未来的AI技术格局。本文将从以下七个方面探讨AI模型的未来之路,并提供实用的代码示例…

ROS1 + Realsense d455 固件安装+读取rostopic数据

目录 安装固件&#xff08;一定要匹配&#xff09;ROS1 wrapper 安装方法Realsense SDK 安装方法Realsense Firmware 安装方法 修改roslaunch配置文件&#xff0c;打开双目图像和IMU数据其他坑点参考链接 安装固件&#xff08;一定要匹配&#xff09; 如果你是使用ROS1获取rea…

Python数据分析-绘制图表

示例1&#xff1a; from pyecharts.charts import Bar # 柱状图 from pyecharts import options as optsfrom pyecharts.render import make_snapshotbar Bar() bar.add_xaxis([一月, 二月, 三月, 四月, 五月]) bar.add_yaxis("销售额", [10, 20, 15, 25, 30])# 配…

安卓framework单屏幕Display秒双/多屏互动相关需求改进-wms实战开发

背景 前面已经给学员朋友们分享过单屏秒变双屏的成果展示&#xff0c;具体详情可以点击这里&#xff1a; https://mp.weixin.qq.com/s/KdYTLMuXiBdjM0kZmYKzPg 一些vip学员朋友也纷纷求助马哥的实现patch代码&#xff0c;想用于公司的实战项目实现。但是在公司需求实现要求和…

Python(TensorFlow)和MATLAB及Java光学像差导图

&#x1f3af;要点 几何光线和波前像差计算入瞳和出瞳及近轴光学计算波前像差特征矩阵方法计算光谱反射率、透射率和吸光度透镜像差和绘制三阶光线像差图和横向剪切干涉图分析瞳孔平面焦平面和大气湍流建模神经网络光学像差计算透镜光线传播几何偏差计算像差和像散色差纠正对齐…

八、Maven总结

1.为什么要学习Maven&#xff1f; 2.Maven 也可以配华为云和腾讯云等。 3.IDEA整合Maven 4.IDEA基于Maven进行工程的构建 5.基于Maven进行依赖管理&#xff08;重点&#xff09; 6. Maven的依赖传递和依赖冲突 7. Maven工程继承和聚合 8.仓库及查找顺序

应用层协议Http

Http协议 1.1 什么是http协议 在进行网络通信时&#xff0c;应用层协议一般都是程序员自己写的&#xff0c;但是有一些大佬其实已经定义出了一些现成的应用层协议&#xff0c;例如&#xff1a;HTTP&#xff08;超文本传输协议&#xff09;、FTP&#xff08;文件传输协议&#…

SAP学习笔记 - 开发04 - Fiori UI5 开发环境搭建

上一章学习了 CDSView开发环境的搭建&#xff0c;以及CDSView相关的知识。 SAP学习笔记 - 开发03 - CDSView开发环境搭建&#xff0c;Eclipse中连接SAP&#xff0c;CDSView创建-CSDN博客 本章继续学习SAP开发相关的内容&#xff0c; - Fiori UI5的开发环境搭建 - 安装VSCode …

百度飞将 paddle ,实现贝叶斯神经网络 bayesue neure network bnn,aistudio公开项目 复现效果不好

论文复现赛&#xff1a;贝叶斯神经网络 - 飞桨AI Studio星河社区 https://github.com/hrdwsong/BayesianCNN-Paddle 论文复现&#xff1a;Weight Uncertainty in Neural Networks 本项目复现时遇到一个比较大的问题&#xff0c;用pytorch顺利跑通源代码后&#xff0c;修改至pad…

【Python报错已解决】 AttributeError: ‘move_to‘ requires a WebElement

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 前言一、问题描述1.1 报错示例1.2 报错分析1.3 解决思路 二、解决方法2.1 方法一&#xff1a;检查元素选择器2.2 方法…

828华为云征文|华为云Flexus X实例docker部署rancher并构建k8s集群

828华为云征文&#xff5c;华为云Flexus X实例docker部署rancher并构建k8s集群 华为云最近正在举办828 B2B企业节&#xff0c;Flexus X实例的促销力度非常大&#xff0c;特别适合那些对算力性能有高要求的小伙伴。如果你有自建MySQL、Redis、Nginx等服务的需求&#xff0c;一定…

一款支持同一个屏幕界面同时播放多个视频的视频播放软件

GridPlayer 是一款基于 VLC 的免费开源跨平台多视频同步播放工具&#xff0c;支持在一块屏幕上同时播放多个视频。其主要功能包括&#xff1a; 多视频播放&#xff1a;用户可以在一个窗口中同时播放任意数量的视频&#xff0c;数量仅受硬件性能限制。支持多种格式和流媒体&…

java实现,PDF转换为TIF

目录 ■JDK版本 ■java代码・实现效果 ■POM引用 ■之前TIF相关的问题&#xff08;两张TIF合并&#xff09; ■对于成果物TIF&#xff0c;需要考虑的点 ■问题 ■问题1&#xff1a;无法生成TIF&#xff0c;已解决 ■问题2&#xff1a;生成的TIF过大&#xff0c;已解决 …

vue3 自定义指令 directive

1、官方说明&#xff1a;https://cn.vuejs.org/guide/reusability/custom-directives 除了 Vue 内置的一系列指令 (比如 v-model 或 v-show) 之外&#xff0c;Vue 还允许你注册自定义的指令 (Custom Directives)。 我们已经介绍了两种在 Vue 中重用代码的方式&#xff1a;组件和…

QT 编译报错:C3861: ‘tr‘ identifier not found

问题&#xff1a; QT 编译报错&#xff1a;C3861&#xff1a; ‘tr’ identifier not found 原因 使用tr的地方所在的类没有继承自 QObject 类 或者在不在某一类中&#xff0c; 解决方案 就直接用类名引用 &#xff1a;QObject::tr( )

ApacheKafka中的设计

文章目录 1、介绍1_Kafka&MQ场景2_Kafka 架构剖析3_分区&日志4_生产者&消费者组5_核心概念总结6_顺写&mmap7_Kafka的数据存储形式 2、Kafka的数据同步机制1_高水位&#xff08;High Watermark&#xff09;2_LEO3_高水位更新机制4_副本同步机制解析5_消息丢失问…

matplotlib中文乱码问题

在使用Matplotlib进行数据可视化的过程中&#xff0c;经常会遇到中文乱码的问题。显示乱码是由于编码问题导致的&#xff0c;而matplotlib 默认使用ASCII 编码&#xff0c;但是当使用pyplot时&#xff0c;是支持unicode编码的&#xff0c;只是默认字体是英文字体&#xff0c;导…

GraphPad Prism 10 for Mac/Win:高效统计分析与精美绘图的科学利器

GraphPad Prism 10 是一款专为科研工作者设计的强大统计分析与绘图软件&#xff0c;无论是Mac还是Windows用户&#xff0c;都能享受到其带来的便捷与高效。该软件广泛应用于生物医学研究、实验设计和数据分析领域&#xff0c;以其直观的操作界面、丰富的统计方法和多样化的图表…

【HuggingFace Transformers】OpenAIGPTModel源码解析

OpenAIGPTModel源码解析 1. GPT 介绍2. OpenAIGPTModel类 源码解析 说到ChatGPT&#xff0c;大家可能都使用过吧。2022年&#xff0c;ChatGPT的推出引发了广泛的关注和讨论。这款对话生成模型不仅具备了强大的语言理解和生成能力&#xff0c;还能进行非常自然的对话&#xff0c…