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…...
FanControl终极指南:免费开源的风扇控制神器,轻松解决Windows散热与噪音问题
FanControl终极指南:免费开源的风扇控制神器,轻松解决Windows散热与噪音问题 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https:…...
Nix构建确定性AI编程环境:解决Cursor编辑器依赖冲突难题
1. 项目概述:当代码编辑器遇上Nix的确定性魔法 最近在折腾开发环境时,我遇到了一个老生常谈但又无比头疼的问题:团队里新来的同事怎么也跑不起来我本地运行得好好的一个代码辅助工具链。依赖版本冲突、系统库路径不对、甚至是因为他用的macO…...
荣品RV1126 SDK编译避坑指南:从环境配置到分区调整,手把手解决常见编译错误
RV1126 SDK编译实战:从环境搭建到分区优化的全流程解决方案 1. 开发环境配置与初始化 RV1126开发环境的搭建是整个开发流程的第一步,也是后续所有工作的基础。一个稳定、高效的开发环境能够显著提升开发效率,减少不必要的错误。 首先需要确保…...
安全聚合技术:原理、实现与多场景应用
1. 安全聚合技术概述安全聚合(Secure Aggregation)是一种多方安全计算技术,它允许多个互不信任的参与方在不泄露各自私有数据的前提下,共同计算出一个聚合结果。这项技术的核心价值在于解决了数据隐私与数据共享之间的矛盾&#x…...
Claude API企业准入最后窗口期:2024Q3起强制启用OAuth 2.1+硬件级密钥绑定,现在不升级将无法续签
更多请点击: https://intelliparadigm.com 第一章:Claude API企业准入政策的演进与合规紧迫性 随着Anthropic对Claude模型商用边界的持续收束,企业级API接入正从“技术可用性”转向“治理可验证性”。2024年Q2起,所有新注册企业账…...
Go语言实现跨平台系统更新检查器:自动化运维与安全监控实践
1. 项目概述:一个被低估的系统运维“哨兵”在服务器和桌面系统的日常运维中,有一个场景大家一定不陌生:某天,你管理的服务器突然因为一个已知漏洞被攻击,事后排查发现,相关的安全补丁其实在几周前就已经发布…...
Gopeed下载器深度解析:从零开始构建你的全平台高速下载解决方案
Gopeed下载器深度解析:从零开始构建你的全平台高速下载解决方案 【免费下载链接】gopeed A fast, modern download manager for HTTP, BitTorrent, Magnet, and ed2k. Cross-platform, built with Golang and Flutter. 项目地址: https://gitcode.com/GitHub_Tre…...
C++运行时类型识别实战:从typeid().name()到可读类型名
1. 为什么我们需要关心运行时类型识别? 在C开发中,我们经常会遇到需要知道某个变量或表达式具体类型的情况。特别是在调试复杂代码、编写泛型程序或进行元编程时,能够准确获取类型信息就显得尤为重要。想象一下,当你看到一个日志输…...
Helm-Intellisense:VS Code智能补全插件,提升values.yaml编写效率
1. 项目概述:为什么我们需要一个Helm智能补全工具?如果你和我一样,日常工作中大量使用Helm来管理Kubernetes应用,那你一定对编写values.yaml文件时那种“盲人摸象”的感觉深有体会。面对一个动辄几十上百行配置的Helm Chart&#…...
多智能体强化学习环境PettingZoo:从核心概念到工程实践
1. 项目概述:从零理解PettingZoo如果你正在寻找一个能让你快速上手、高效构建多智能体强化学习(Multi-Agent Reinforcement Learning, MARL)实验环境的工具,那么Farama Foundation旗下的PettingZoo项目,绝对是你绕不开…...

