Apache POI 实现用Java操作Excel完成读写操作
简介
Apache POI是一个用于操作Microsoft Office格式文件(包括xls、docx、xlsx、pptx等)的Java API库。POI全称为Poor Obfuscation Implementation,是Apache Software Foundation的一个开源项目。它提供了一组Java API,使得Java程序可以读取、写入和操作Microsoft Office格式文件。
具体来说,POI提供了以下几种主要的组件:
- HSSF:用于读写Excel 97-2003格式的xls文件。
- XSSF:用于读写Excel 2007格式的xlsx文件。
- SXSSF:是Apache POI中用于处理大量数据的API,它基于XSSF,可以处理Excel 2007及以上版本的xlsx文件。SXSSF的特点在于它可以将大量数据分成多个部分进行处理,从而减少内存的占用,提高处理大量数据的效率。
- HWPF:用于读写Word 97-2003格式的doc文件。
- XWPF:用于读写Word 2007格式的docx文件。
- HSLF:用于读写PowerPoint 97-2003格式的ppt文件。
- XSLF:用于读写PowerPoint 2007格式的pptx文件。
这里先介绍使用Apache POI 如何操作excel
环境准备
Maven仓库
- jdk1.8
- poi-3.9
- poi-ooxml-3.9
- poi-ooxml-schemas-3.9
- xmlbeans-2.6.0
- junit4.12
- joda-time-2.10.1
写入Excel文件
Excel 97-2003 和 2007的区别?
- 文件格式不同:
- Excel 97-2003使用的是 .xls格式,.xls格式采用二进制格式存储数据,
- 而Excel 2007使用的是 .xlsx格式。而.xlsx格式采用了基于XML的压缩文件格式。
- 大小限制不同:
- Excel 97-2003的工作表大小限制为65536行、256列。
- Excel 2007的工作表大小限制为1048576行、16384列。
API介绍
- Workbook:表示一个Excel工作簿,包括多个Sheet,提供了创建Sheet、读取Sheet、写入Sheet等方法。
- Sheet:表示一个Excel工作表,包括多个Row,提供了读取Row、写入Row、创建Cell等方法。
- Row:表示Excel工作表中的一行,包括多个Cell,提供了读取Cell、写入Cell等方法。
- Cell:表示Excel工作表中的一个单元格,提供了读取单元格值、写入单元格值、设置单元格样式等方法。
小文件写入
注意:代码中的 PATH 是声明的静态类变量,是基础的文件路径
static String PATH = "D:\\poi\\";
03版本-小文件写入
//03版本-小数据写入@Testpublic void testWrite03() throws IOException {/*** 1.创建一个03版的工作簿* HSSF-03版本* XSSF=07版本* SXSSF-加速处理07版本*/Workbook workbook = new HSSFWorkbook();/*** 2.创建一个工作表* 通过工作簿来新建工作表,因为工作簿在工作表之上*/Sheet sheet = workbook.createSheet("表1");/*** 3.创建一个行* 通过表创建行,因为表在行之上* 0代表第一行*/Row row1 = sheet.createRow(0);/*** 4.创建单元格* 通过行创建单元格*/Cell cell1_1 = row1.createCell(0);//第一行第一列cell1_1.setCellValue("id");Cell cell1_2 = row1.createCell(1);//第一行第二列cell1_2.setCellValue("name");Cell cell1_3 = row1.createCell(2);//第一行第三列cell1_3.setCellValue("birth");//第二行Row row2 = sheet.createRow(1);Cell cell2_1 = row2.createCell(0);//第二行第一列cell2_1.setCellValue(1);Cell cell2_2 = row2.createCell(1);//第二行第二列cell2_2.setCellValue("嘴哥");Cell cell2_3 = row2.createCell(2);//第一行第三列//使用 joda包创建时间String time = new DateTime().toString("yyyy-MM-dd");cell2_3.setCellValue(time);//生成一张表 03版本用 xls 结尾File file = new File(PATH+"03_1.xls");FileOutputStream outputStream = new FileOutputStream(file);//输出到本地workbook.write(outputStream);//关闭流outputStream.close();System.out.println("文件生成完毕!");}
运行结果
07版本-小文件写入
//07版本-小数据写入@Testpublic void testWrite07() throws IOException {/*** 1.创建一个03版的工作簿* HSSF-03版本* XSSF=07版本* SXSSF-加速处理07版本*/Workbook workbook = new XSSFWorkbook();/*** 2.创建一个工作表* 通过工作簿来新建工作表,因为工作簿在工作表之上*/Sheet sheet = workbook.createSheet("表1");/*** 3.创建一个行* 通过表创建行,因为表在行之上* 0代表第一行*/Row row1 = sheet.createRow(0);/*** 4.创建单元格* 通过行创建单元格*/Cell cell1_1 = row1.createCell(0);//第一行第一列cell1_1.setCellValue("id");Cell cell1_2 = row1.createCell(1);//第一行第二列cell1_2.setCellValue("name");Cell cell1_3 = row1.createCell(2);//第一行第三列cell1_3.setCellValue("birth");//第二行Row row2 = sheet.createRow(1);Cell cell2_1 = row2.createCell(0);//第二行第一列cell2_1.setCellValue(1);Cell cell2_2 = row2.createCell(1);//第二行第二列cell2_2.setCellValue("嘴哥");Cell cell2_3 = row2.createCell(2);//第一行第三列//使用 joda包创建时间String time = new DateTime().toString("yyyy-MM-dd");cell2_3.setCellValue(time);//生成一张表 03版本用 xls 结尾File file = new File(PATH+"03_1.xlsx");FileOutputStream outputStream = new FileOutputStream(file);//输出到本地workbook.write(outputStream);//关闭流outputStream.close();System.out.println("文件生成完毕!");}
运行结果
大文件写入
03版本-大文件写入
//03版本-大数据写入65536行 1400ms@Testpublic void testWrite03BigData() throws IOException {//开始时间long begin = System.currentTimeMillis();//创建一个工作簿Workbook workbook = new HSSFWorkbook();//创建表Sheet sheet = workbook.createSheet();//写入数据for (int rowNums = 0; rowNums < 65536; rowNums++) {Row row = sheet.createRow(rowNums);for (int cellNums = 0; cellNums < 10; cellNums++) {Cell cell = row.createCell(cellNums);cell.setCellValue(cellNums);}}System.out.println("over");FileOutputStream outputStream = new FileOutputStream(new File(PATH + "bigData03.xls"));workbook.write(outputStream);outputStream.close();//结束时间long end = System.currentTimeMillis();System.out.println("总用时 "+(end-begin)+"ms");}
07版本-大文件写入
//07版本-大数据写入65537行 6856ms@Testpublic void testWrite07BigData() throws IOException {//开始时间long begin = System.currentTimeMillis();//创建一个工作簿Workbook workbook = new XSSFWorkbook();//创建表Sheet sheet = workbook.createSheet();//写入数据for (int rowNums = 0; rowNums < 65537; rowNums++) {Row row = sheet.createRow(rowNums);for (int cellNums = 0; cellNums < 10; cellNums++) {Cell cell = row.createCell(cellNums);cell.setCellValue(cellNums);}}System.out.println("over");FileOutputStream outputStream = new FileOutputStream(new File(PATH + "bigData03.xlsx"));workbook.write(outputStream);outputStream.close();//结束时间long end = System.currentTimeMillis();System.out.println("总用时 "+(end-begin)+"ms");}
运行结果
07升级版-大文件写入
//07升级版-大数据写入10w行 1814ms@Testpublic void testWrite07BigDataS() throws IOException {//开始时间long begin = System.currentTimeMillis();//创建一个工作簿Workbook workbook = new SXSSFWorkbook();//创建表Sheet sheet = workbook.createSheet();//写入数据for (int rowNums = 0; rowNums < 100000; rowNums++) {Row row = sheet.createRow(rowNums);for (int cellNums = 0; cellNums < 10; cellNums++) {Cell cell = row.createCell(cellNums);cell.setCellValue(cellNums);}}System.out.println("over");FileOutputStream outputStream = new FileOutputStream(new File(PATH + "bigData03S.xlsx"));workbook.write(outputStream);//关闭资源outputStream.close();//关闭临时文件((SXSSFWorkbook)workbook).dispose();//结束时间long end = System.currentTimeMillis();System.out.println("总用时 "+(end-begin)+"ms");}
总结
- HSSF:适用于读写Excel 97-2003格式的xls文件,可以处理一般大小的数据,缺点是处理大量数据时,会占用大量内存,导致程序运行较慢。
- XSSF:适用于读写Excel 2007及以上版本的xlsx文件,支持更多的行列数、更好的样式支持等,但处理大量数据时,仍然会占用大量内存,不适合处理大数据量的情况。
- SXSSF:基于XSSF,适用于处理大量数据,可以将大量数据分成多个部分进行处理,从而减少内存的占用,提高处理大量数据的效率。但不支持公式计算等高级功能。
综上,选择API应根据具体的需求和数据量来决定。如果处理的数据量较小,可以选择HSSF或XSSF;如果需要处理大量数据,可以选择SXSSF。如果需要同时兼顾处理大量数据和高级功能,可以考虑使用HSSF或XSSF与SXSSF结合的方式来处理数据。
03版-文件读取
@Testpublic void testRead03() throws IOException {//获取文件流FileInputStream inputStream = new FileInputStream(new File(PATH+"03_1.xls"));//1.创建一个工作簿,使用excel能操作的,它都可以操作Workbook workbook = new HSSFWorkbook(inputStream);//2.获取表Sheet sheet0 = workbook.getSheetAt(0);//3.得到行Row row = sheet0.getRow(1);//获取第1行//4.得到列Cell cell = row.getCell(0);//获取第一行第一列//以Number形式输出-可以选择格式//必须对应格式-number类型不可以转为String类型!!System.out.println(cell.getNumericCellValue());//关闭流资源inputStream.close();}
07版本-文件读取
@Testpublic void testRead07() throws IOException {//获取文件流FileInputStream inputStream = new FileInputStream(new File(PATH+"03_1.xlsx"));//1.创建一个工作簿,使用excel能操作的,它都可以操作Workbook workbook = new XSSFWorkbook(inputStream);//2.获取表Sheet sheet0 = workbook.getSheetAt(0);//3.得到行Row row = sheet0.getRow(1);//获取第1行//4.得到列Cell cell = row.getCell(0);//获取第一行第一列//以Number形式输出-可以选择格式//必须对应格式-number类型不可以转为String类型!!System.out.println(cell.getNumericCellValue());//关闭流资源inputStream.close();}
不同类型数据的读取
针对字符串、数值类型、日期等需要不同的处理方式。
//测试读取不同类型的数据 03版本@Testpublic void testCellType() throws IOException {FileInputStream inputStream = new FileInputStream(new File(PATH+"test03.xls"));Workbook workbook = new HSSFWorkbook(inputStream);Sheet sheet = workbook.getSheetAt(0);//读取标题内容Row title = sheet.getRow(0);if (title != null){int columns = title.getPhysicalNumberOfCells();//列数for (int cellNum = 0; cellNum < columns; cellNum++) {Cell cell = title.getCell(cellNum);if (cell != null){int cellType = cell.getCellType();//我们已知为StringString cellValue = cell.getStringCellValue();System.out.print(cellValue+" | ");}}System.out.println();}//读取表中的内容int rows = sheet.getPhysicalNumberOfRows();//行数for (int rowNum = 1; rowNum < rows; rowNum++) {Row row = sheet.getRow(rowNum);if (row != null){//读取行中的列int columns = title.getPhysicalNumberOfCells();for (int col = 0; col < columns; col++) {System.out.print("["+(rowNum+1)+"-"+(col+1)+"]");Cell cell = row.getCell(col);//匹配列的数据类型if (cell != null){int cellType = cell.getCellType();String cellValue = "";switch (cellType){case HSSFCell.CELL_TYPE_STRING://字符串System.out.print("[STRING]");cellValue = cell.getStringCellValue();break;case HSSFCell.CELL_TYPE_NUMERIC://数字(日期、数字)if (HSSFDateUtil.isCellDateFormatted(cell)){//日期System.out.print("[DATE]");Date date = cell.getDateCellValue();cellValue = new DateTime(date).toString("yyyy-MM-dd");}else{System.out.print("[NUMBER]");//防止数字过长,转为Stringcell.setCellType(HSSFCell.CELL_TYPE_STRING);cellValue = cell.toString();}break;case HSSFCell.CELL_TYPE_BLANK://空System.out.print("[NULL]");break;case HSSFCell.CELL_TYPE_BOOLEAN://布尔System.out.print("[BOOLEAN]");cellValue = String.valueOf(cell.getBooleanCellValue());case HSSFCell.CELL_TYPE_ERROR:System.out.print("[ERROR]");cellValue = String.valueOf(cell.getErrorCellValue());break;}System.out.println(cellValue);}}}}inputStream.close();}
相关文章:

Apache POI 实现用Java操作Excel完成读写操作
简介 Apache POI是一个用于操作Microsoft Office格式文件(包括xls、docx、xlsx、pptx等)的Java API库。POI全称为Poor Obfuscation Implementation,是Apache Software Foundation的一个开源项目。它提供了一组Java API,使得Java程…...

改善供应商关系的八种方法
与供应商保持良好关系的重要性有很多原因。最重要的是,它使每个人的日常工作更加愉快。它还可以为你获得更好的交易,有助于协作并增强商誉。 但是,每个供应商都是不同的,建立牢固的关系可能很棘手。本文将解释企业如何建立并操持…...

网络安全-CDN绕过寻找真实IP
网络安全-CDN绕过寻找真实IP CDN就是CDN加速,就是根据你的目标让你访问的更快 CDN CDN,即内容分发网络,主要解决因传输距离和不同运营商节点造成的网络速度性能低下的问题。说得简单点,就是一组在不同运营商之间的对接节点上的…...

牛客网 HJ28 素数伴侣【二分图匹配,匈牙利算法】困难
描述 若两个正整数的和为素数,则这两个正整数称之为“素数伴侣”,如2和5、6和13,它们能应用于通信加密。现在密码学会请你设计一个程序,从已有的 N ( N 为偶数)个正整数中挑选出若干对组成“素数伴侣”&am…...

带你畅玩ChatGPT
ChatGPT出来很久了,最近不少朋友还是不太会使用ChatGPT体验与机器人进行聊天,我正好发现有种非常简单的方式帮助大家体验ChatGPT,且响应速度非常快,写代码能力也不错,现在推荐给大家,希望对大家有所帮助。 目录 一、下载专用浏览器 1.1 下载链接 1.2 安装浏览器 二、…...

ChatGPT探索系列之六:思考ChatGPT的未来发展趋势和挑战
文章目录 前言一、未来发展趋势1. ChatGPT重塑数据分析之道2. ChatGPT颠覆企业运用人工智能和机器学习的途径3. ChatGPT颠覆自动化商业流程4. ChatGPT引领企业决策迈向新纪元 二、ChatGPT掀开未来充满机遇和挑战的新篇章总结 前言 ChatGPT发展到目前,其实网上已经有…...

TryHackMe-Year of the Fox(Linux渗透测试)
Year of the Fox 你能熬过狡猾的狐狸吗? 端口扫描 循例nmap 有个域名,加入hosts SMB枚举 smbmap enum4linux -a,枚举到两个账户 Web枚举 进80发现需要登录 上hydra RCE to Getshell 进来可以查看一些文件 bp发现这里存在过滤 burpfuzz一…...

ChatGPT 如何获取API Key
什么是OpenAI API Key? OpenAI是ChatGPT的“开发商”,提供API使得开发者可以在自己的应用程序上调用OpenAI的相关服务(除了ChatGPT,OpenAI还有其他产品)。如果想调用OpenAI的产品服务在自己的应用程序上,我们就需要申…...

明面抵制,暗中布局 对于AI,马斯克的言行为何如此“割裂”?
最近,马斯克创建了一家叫做“X”的空壳公司,目标是将其打造成涵盖各方面的多功能应用集合平台,推特、SpaceX、特斯拉、Neuralink等公司业务都已打包加入其中。如今,“X”公司再添新丁——X.AI,即马斯克新成立的人工智能…...

【微服务中间件学习】redis基础及项目使用
背景 最近跟着大佬学习,发现之前都是一知半解,还是得系统学一下。 重温redis,有一下整理Redis是一种基于内存的高性能键值存储系统,它支持多种数据结构和持久化方式,并提供了许多高级功能,如发布/订阅、事…...

ORA-04021:等待锁定对象时发生超时
现场人员反馈问题,drop表报错,如下图 是个rac环境,处理过程 1、2个节点上查看锁表,没任何输出 SYSorcl2> select name from v$db_object_cache where ownerUSR_DATAI and type in(PROCEDURE,FUNCTION) and locks > 0 and …...

【华为OD机试真题 C++】1066 - 新工号中数字的最短长度 | 机试题+算法思路+考点+代码解析
文章目录 一、题目🔸题目描述🔸输入输出🔸样例1🔸样例2🔸样例3 二、代码参考 作者:KJ.JK 🌈 🌈 🌈 🌈 🌈 🌈 🌈 …...

【数字 IC / FPGA】 有关建立/保持时间计算的思考
引言 最近准备一些数字IC的机试,刷到了一些有关静态时序分析的题目。有一些比较经典的题目,在这里整理分享一下。 有什么疑问可以在评论区交流~互相进步 双D触发器典型电路 假设时钟周期为Tcycle,Tsetup,Thold分别为触发器建立保持时间,为…...

【Fluent】Run can not be started until validation issues are resolved.
一、问题背景 因为在fluent中用Discard Data, Replace Mesh选项替换了网格,但是没有抛弃算例设置等参数。 当时我以为网格是完全一样的,便忽略了产生冲突/错误的可能。 之后在calculate的时候,报错:Run can not be started unt…...

【进阶C语言】有关动态内存管理的经典笔试题(详细图文讲解)
前言 📕作者简介:热爱跑步的恒川,致力于C/C、Java、Python等多编程语言,热爱跑步,喜爱音乐的一位博主。 📗本文收录于C语言进阶系列,本专栏主要内容为数据的存储、指针的进阶、字符串和内存函数…...

1.Java系列之基础面试题总结
1. 构造器是否可重写 首先,构造器是不能被继承的,因为每个类的类名都不相同,而构造器名称与类名相同,所以根本谈不上继承。 又由于构造器不能继承,所以就不能被重写。但是,在同一个类中,构造器…...

Android:usb转232串口通信
准备工作 首先得adb进入盒子root模式,将/dev/ttys1这个文件改为777,使得所有用户可操作 adb root adb remount adb shell 进入设备的root模式,执行 chmod 777 /dev/ttys1 执行完成后退出 exit 再执行 adb shell chmod 666 /dev/ttyS1 如…...

动态设置图片的主题色(保留明暗关系)
github地址 PrimaryColorDemo 效果 原始图片 就是一张普通的png图片 根据选择的主题色动态渲染。 思考 最近在思考怎么实现动态的设置图片的主题色。不是那种渲染透明iocn。而是把图片的明暗关系保留。而改变其中的主题色。终于花了半天的时间研究出来了。和大家共享。 …...

mybatis中#与$的区别
文章目录 区别详细讲解${}sql注入案例 区别 #会进行预编译,安全,通过#{}传入的参数 mybatis会认为是一个字符串,自动加上引号“” $ 不会进行预编译,通过$ 传入的参数会直接取出来使用,可能会产生sql注入风险ÿ…...

CVPR2023论文整理
文章目录 CVPR2023一. Vision and Language / Multimodal CVPR2023 根据官方信息统计,今年共收到 9155 份提交,比去年增加了 12%,创下新纪录,今年接收了 2360 篇论文,接收率为 25.78%。作为对比,去年有 81…...

RK3399平台开发系列讲解(中断篇)掌握信号处理
🚀返回专栏总目录 文章目录 一、信号的基本概念二、信号处理流程三、如何通过 API 注册一个信号处理函数四、可重入与异步信号安全3.1、可重入函数3.2、异步信号安全沉淀、分享、成长,让自己和他人都能有所收获!😄 📢信号在操作系统中有悠久的历史,信号的概念和使用方…...

业余爱好者想入门编程,一定远离那些只会说No的家伙,尤其程序员
视频:https://haokan.baidu.com/v?pdwisenatural&vid3050207991292418741 自媒体上的程序员群体有一个非常有意思的特点,就是特别愿意否定别人,特别喜欢说no,还有一个特点,特别不爱分享一些有用的技术和知识&…...

DHCP及中继(UOS)
DHCP服务器 中继器 客户端 服务器 安装DHCP apt install isc-dhcp-server -y 编辑配置文件 vim /etc/dhcp/dhcpd.conf 重启服务 systemctl restart isc-dhcp-server 配置监听网卡 vim /etc/default/isc-dhcp-server 中继器 安装dhcp yum install dhcp -y nmtui 修改…...

【Linux】进程的概念
文章目录 📖 前言1. 冯诺依曼体系结构1.1 内存存在的意义:1.2 程序加载到内存的意义:1.3 程序的预加载: 2. 认识进程2.1 如何理解管理:2.2 什么叫是进程:(初步理解) 3. 简单认识操作…...

奇舞周刊第490期:WebAssembly 多语言/宿主环境中的使用
记得点击文章末尾的“ 阅读原文 ”查看哟~ 下面先一起看下本期周刊 摘要 吧~ 奇舞精选 ■ ■ ■ WebAssembly 多语言/宿主环境中的使用 WebAssembly (WASM) 的一个优势就是能够支持将不同语言编译成 WASM 代码,然后在不同的宿主环境中运行。这样就可以在不同的宿主环…...

【css】使用css实现提示框各种弹出效果。
简言 最近工作编写页面时,需要有一个提示框从下到上弹出的效果。 冥想了一下,实现了出来。 记录下实现思路。 实现思路 实现步骤如下: 编写样式。 首页要有承载内容的容器(box)。外层在套一个包装盒子(用来进行定位…...

1685_Excel的几种脚本处理方式
全部学习汇总: GreyZhang/python_basic: My learning notes about python. (github.com) 做个小结,实际上是写的我自己学习的过程。 关于Excel的处理方式很多,我也不会那么多,在这里我只想写一下我自己接触过的。大致是三种方式&a…...

Unity中使用struct和class来存储数据的注意事项
在 Unity 中,struct 和 class 都是用来定义自定义类型的关键字。它们的主要区别在于如何存储和传递它们的实例。 特点structclass存储方式值类型引用类型默认构造函数自动有性能快慢可空性不可空可空继承单继承单继承或多重继承 一、相似之处 1、都是用来定义自定…...

共阳(共阴)LED数码管编码交互演示
LED数码管原理 LED数码管有两大类,一类是共阴极接法,另一类是共阳极接法,共阴极就是各段的显示字码共用一个电源的负极,是高电平点亮,共阳极就是各段的显示字码共用一个电源的正极,是低电平点亮。只要控制…...

如何在 TensorFlow 中使用 GPU 加速深度学习计算?
一、前言 TensorFlow 是由 Google 开源的深度学习框架,它具有易用、高效、灵活等特点,被广泛应用于学术界和工业界中。而 GPU 是一种高性能的计算设备,可以加速深度学习的计算过程。本文将介绍如何在 TensorFlow 中使用 GPU 加速深度学习计算。 二、安装 TensorFlow 安装…...