news 2026/7/21 7:58:10

【苍穹外卖 Day12| Excel 入门】

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【苍穹外卖 Day12| Excel 入门】

前言

后台系统经常要和 Excel 打交道:把数据整理成表格交给运营人员,或者读取已有表格继续处理。Apache POI 提供了 Java 操作 Office 文件的能力,本节先把最基础的 Excel 写入和读取流程走通。

本文只讨论 XLSX 文件的基础读写。工作台的营业数据报表导出属于这套能力的后续应用,文末只作简要说明。

一、Apache POI 能做什么

Apache POI 是 Java 操作 Microsoft Office 文件的开源项目,其中最常用的场景是处理 Excel。

Excel 有两种常见格式:

  • .xls:旧版 Excel 格式;
  • .xlsx:新版 Excel 格式。

本节使用的是 XLSX,所以代码中使用 XSSFWorkbook、XSSFSheet、XSSFRow 和 XSSFCell。它们之间的层级关系可以这样理解:

XSSFWorkbook 一个 Excel 工作簿 └── XSSFSheet 工作表,例如“Sheet1” └── XSSFRow 一行数据 └── XSSFCell 一个单元格

后续无论是自己创建表格,还是打开一个已有模板,本质上都是沿着这个结构定位数据。

二、项目中的 POI 依赖

学习笔记中的入门代码使用的是 POI 3.16。当前苍穹外卖项目在父工程 pom.xml 中统一管理的版本为 5.3.0,并同时引入了下面两个依赖:

<dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>${poi}</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>${poi}</version></dependency>

其中,poi-ooxml 用于处理 XLSX 这类 OOXML 格式文件。实际写项目时,优先跟随当前工程已经声明的版本,不要再额外混入笔记中的旧版本依赖。

三、把数据写入 Excel 文件

写入 Excel 的顺序很固定:先在内存中创建工作簿,再创建工作表、行和单元格,最后通过输出流写到磁盘。

importorg.apache.poi.xssf.usermodel.XSSFRow;importorg.apache.poi.xssf.usermodel.XSSFSheet;importorg.apache.poi.xssf.usermodel.XSSFWorkbook;importjava.io.FileOutputStream;publicclassPOITest{publicstaticvoidwrite()throwsException{try(XSSFWorkbookworkbook=newXSSFWorkbook();FileOutputStreamoutputStream=newFileOutputStream("D:/itcast.xlsx")){XSSFSheetsheet=workbook.createSheet("itcast");XSSFRowrow1=sheet.createRow(0);row1.createCell(1).setCellValue("姓名");row1.createCell(2).setCellValue("城市");XSSFRowrow2=sheet.createRow(1);row2.createCell(1).setCellValue("张三");row2.createCell(2).setCellValue("北京");XSSFRowrow3=sheet.createRow(2);row3.createCell(1).setCellValue("李四");row3.createCell(2).setCellValue("上海");workbook.write(outputStream);}}}

这段代码中,new XSSFWorkbook() 只是在内存里创建 Excel 对象,还没有生成文件。createSheet(“itcast”) 创建名为 itcast 的工作表;createRow(0) 创建第一行;createCell(1) 创建该行的第二个单元格。

最后调用 workbook.write(outputStream),工作簿中的内容才会通过 FileOutputStream 写入 D:/itcast.xlsx。运行后打开文件,可以看到姓名、城市以及两行示例数据。

这里推荐使用 try-with-resources。工作簿和输出流会在代码块结束后自动关闭,避免文件被占用或资源泄漏。

四、从 Excel 文件读取数据

读取操作和写入操作正好相反:先通过输入流打开文件,再获取工作表、行和单元格,最后读取单元格内容。

importorg.apache.poi.xssf.usermodel.XSSFCell;importorg.apache.poi.xssf.usermodel.XSSFRow;importorg.apache.poi.xssf.usermodel.XSSFSheet;importorg.apache.poi.xssf.usermodel.XSSFWorkbook;importjava.io.FileInputStream;publicclassPOITest{publicstaticvoidread()throwsException{try(FileInputStreaminputStream=newFileInputStream("D:/itcast.xlsx");XSSFWorkbookworkbook=newXSSFWorkbook(inputStream)){XSSFSheetsheet=workbook.getSheetAt(0);intlastRowNum=sheet.getLastRowNum();for(inti=0;i<=lastRowNum;i++){XSSFRowrow=sheet.getRow(i);XSSFCellnameCell=row.getCell(1);XSSFCellcityCell=row.getCell(2);Stringname=nameCell.getStringCellValue();Stringcity=cityCell.getStringCellValue();System.out.println(name+" "+city);}}}}

new XSSFWorkbook(inputStream) 会根据输入流加载已有的 Excel 文件。getSheetAt(0) 获取第一个工作表,getLastRowNum() 获取最后一行的行号,因此循环条件要写成 i <= lastRowNum。

每次循环先取出当前行,再取第 2、3 个单元格,最后用 getStringCellValue() 得到文本内容。这个示例写入的全部是字符串,所以可以直接按字符串读取。

五、两个容易写错的细节

1. 行号和列号从 0 开始

POI 的行、列下标都从 0 开始:

createRow(0) 第 1 行 createCell(0) 第 1 列 createCell(1) 第 2 列

示例把数据写到第 2、3 列,所以使用的是 createCell(1) 和 createCell(2)。如果把 Excel 中看到的“第几列”直接当成 POI 的下标,就会出现整体错位。

2. 空行、空单元格和数据类型需要额外判断

入门示例中的每一行、每个单元格都已提前写入数据,读取时可以直接调用方法。真实 Excel 往往包含空行、空单元格、数字或日期;这时直接调用 getStringCellValue() 可能抛出异常。

处理外部上传的表格时,应先判断 row 和 cell 是否为空,再按单元格实际类型读取。基础练习先把“工作簿 → 工作表 → 行 → 单元格”的定位链路记清楚,后续再补充类型处理会更稳。

六、项目中的后续使用

当前项目已经在 ReportServiceImpl 中使用 POI 读取运营数据报表模板:先加载运营数据报表模板.xlsx,再按工作表名取得 sheet,随后定位固定行和单元格填入营业额、订单完成率、新增用户等数据,最后把工作簿写到 HTTP 响应输出流。

这说明报表导出并没有脱离本节基础:它只是把“自己创建工作簿”换成了“读取现成模板”,再按行列坐标填充数据。先掌握本节的读写操作,后面理解模板报表会轻松很多。

总结

Apache POI 操作 XLSX 的核心结构是工作簿、工作表、行和单元格。写文件时从内存对象逐层创建后输出到磁盘;读文件时从输入流加载后逐层定位并取值。记住下标从 0 开始,并及时关闭工作簿和流,就能完成最基础的 Excel 读写。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/21 7:57:54

C++多态实战:用组装电脑案例理解虚函数与接口设计

1. 项目概述&#xff1a;从“组装电脑”到理解C多态最近在带新人&#xff0c;发现很多朋友对C面向对象里的“多态”概念&#xff0c;理解起来总感觉隔着一层纱。书上讲虚函数、讲基类指针&#xff0c;例子也多是“动物叫”、“图形面积”这类经典但略显抽象的例子。今天&#x…

作者头像 李华
网站建设 2026/7/21 7:57:24

Agent-Reach 完全指南:用 CLI 一键给 AI Agent 接入 15 个互联网平台

前言Agent-Reach 完全指南&#xff1a;用 CLI 一键给 AI Agent 接入 15 个互联网平台一、为什么 Agent 总是"断网"&#xff1f;二、Agent-Reach 是什么&#xff1f;先看清定位2.1 项目基本信息2.2 它和同类方案的核心差异2.3 适合谁用&#xff1f;三、三条命令走完安…

作者头像 李华
网站建设 2026/7/21 7:56:43

Unity新输入系统实战:从事件驱动到跨平台输入架构设计

1. 项目概述&#xff1a;为什么Unity新输入系统是跨平台开发的“定海神针” 如果你正在用Unity做跨平台游戏&#xff0c;尤其是涉及到PC、主机、移动端多端发布&#xff0c;那么你一定被输入处理折磨过。回想一下&#xff0c;是不是写过一堆 if (Input.GetKeyDown(KeyCode.Spa…

作者头像 李华
网站建设 2026/7/21 7:56:34

多模态AI模型:技术突破与产业应用全景

1. 项目概述&#xff1a;多模态AI模型的崛起与产业机遇 最近半年&#xff0c;国内AI领域最让我兴奋的变化莫过于多模态大模型的快速崛起。作为一名跟踪AI产业多年的从业者&#xff0c;我清晰地记得三年前当GPT-3问世时&#xff0c;国内团队还在单模态语言模型上苦苦追赶。而今天…

作者头像 李华
网站建设 2026/7/21 7:54:46

TI处理器PLL时钟树配置实战:uPP与McASP外设时钟精准设计

1. 项目概述与核心价值在嵌入式系统开发&#xff0c;尤其是基于TI处理器&#xff08;如OMAP-L138、AM335x等系列&#xff09;的项目中&#xff0c;时钟系统的配置往往是项目启动和稳定运行的第一个“拦路虎”。很多工程师拿到芯片手册&#xff0c;看到PLL、SYSCLK、LPSC、CFGCH…

作者头像 李华