【苍穹外卖 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。它们之间的层级关系可以这样理解:

text 复制代码
XSSFWorkbook  一个 Excel 工作簿
└── XSSFSheet  工作表,例如"Sheet1"
    └── XSSFRow  一行数据
        └── XSSFCell  一个单元格

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

二、项目中的 POI 依赖

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

xml 复制代码
<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 的顺序很固定:先在内存中创建工作簿,再创建工作表、行和单元格,最后通过输出流写到磁盘。

java 复制代码
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.FileOutputStream;

public class POITest {

    public static void write() throws Exception {
        try (XSSFWorkbook workbook = new XSSFWorkbook();
             FileOutputStream outputStream = new FileOutputStream("D:/itcast.xlsx")) {

            XSSFSheet sheet = workbook.createSheet("itcast");

            XSSFRow row1 = sheet.createRow(0);
            row1.createCell(1).setCellValue("姓名");
            row1.createCell(2).setCellValue("城市");

            XSSFRow row2 = sheet.createRow(1);
            row2.createCell(1).setCellValue("张三");
            row2.createCell(2).setCellValue("北京");

            XSSFRow row3 = 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 文件读取数据

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

java 复制代码
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.FileInputStream;

public class POITest {

    public static void read() throws Exception {
        try (FileInputStream inputStream = new FileInputStream("D:/itcast.xlsx");
             XSSFWorkbook workbook = new XSSFWorkbook(inputStream)) {

            XSSFSheet sheet = workbook.getSheetAt(0);
            int lastRowNum = sheet.getLastRowNum();

            for (int i = 0; i <= lastRowNum; i++) {
                XSSFRow row = sheet.getRow(i);
                XSSFCell nameCell = row.getCell(1);
                XSSFCell cityCell = row.getCell(2);

                String name = nameCell.getStringCellValue();
                String city = cityCell.getStringCellValue();
                System.out.println(name + " " + city);
            }
        }
    }
}

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

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

五、两个容易写错的细节

1. 行号和列号从 0 开始

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

text 复制代码
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 读写。

相关推荐
用户2986985301412 小时前
Python 数据处理:XML 与 Excel 互转的实用指南
后端·python·excel
xiaopai9451 天前
采购系统和Excel表格区别:钢结构项目物资管理的真实较量
excel·建米软件·采购系统
协享科技1 天前
2026 年 AI 表格工具怎么选:ChatGPT、原生 Copilot/Gemini 与公式助手
人工智能·chatgpt·excel·copilot
用户298698530141 天前
前端实战:在 React 中使用 JavaScript 一键导出 Excel 图表与形状为图片
javascript·react.js·excel
Q一件事2 天前
arcpy实现分区统计到一张excel中
excel
AI刀刀2 天前
deepseek 内容粘贴后符号丢失怎么办?AI 导出鸭实测解决排版乱码问题
android·人工智能·excel·ai导出鸭
圣光SG3 天前
Excel 函数大全
算法·excel
小小的木头人3 天前
Python 批量解析 Excel 经纬度,调用高德地图 API 获取中文地址
开发语言·python·excel
观远数据3 天前
从离线开发到实时同步:DataFlow如何支撑企业级数据治理闭环
java·windows·microsoft·excel