介绍java中常用于处理 Excel 文件的Apache POI
一、介绍
Apache POI(Poor Obfuscation Implementation )是 Apache 基金会的开源 Java 库,用于处理 Microsoft Office 格式文件(如 Excel、Word、PowerPoint)。其中,处理 Excel 2007 及以上版本的.xlsx文件需使用XSSF(XML Spreadsheet Format)组件。
二、组件
- XSSFWorkbook :表示整个
.xlsx工作簿(Workbook)。 - XSSFSheet:表示工作簿中的工作表(Sheet)。
- XSSFRow:表示工作表中的行(Row)。
- XSSFCell:表示行中的单元格(Cell)。
- XSSFCellStyle:单元格样式(字体、颜色、对齐方式等)。
- XSSFFont:字体样式。
在 Apache POI 处理 Excel 文件的层级模型中,Workbook(工作簿)→ Sheet(工作表)→ Row(行)→ Cell(单元格) 是对 Excel 文件结构的抽象映射,对应 Excel 文件的实际组成部分:
1. Workbook(工作簿)
- 对应 Excel 文件本身 :一个
.xlsx文件就是一个 Workbook(工作簿)。 - 作用:作为整个 Excel 文件的顶层容器,包含所有工作表(Sheet)、样式、字体等全局资源。
- POI 实现类:
XSSFWorkbook:对应.xlsx格式(Excel 2007+)。SXSSFWorkbook:用于处理大数据量的.xlsx文件(流式处理,低内存占用)。HSSFWorkbook:对应.xls格式(Excel 97-2003,已过时)。
如图:

2. Sheet(工作表)
- 对应 Excel 中的 "Sheet 标签页":一个工作簿中可以包含多个工作表(如 "Sheet1""Sheet2")。
- 作用:作为行(Row)和单元格(Cell)的容器,负责组织表格数据结构。
- POI 实现类:
XSSFSheet:.xlsx文件的工作表。SXSSFSheet:流式处理的工作表。
如图(一个Workbook下的两个不同的Sheet):


3. Row(行)
- 对应 Excel 表格中的一行 :每个工作表由若干行组成,行索引从0开始(第一行是 Row 0)。
- 作用:作为单元格(Cell)的直接容器,每行包含多个单元格。
- POI 实现类:
XSSFRow:.xlsx文件的行。- 注意:行对象可能为
null(表示该行无数据)。
如图:

4. Cell(单元格)
- 对应 Excel 表格中的单元格 :每行由若干单元格组成,列索引从0开始(第一列是 Cell 0)。
- 作用:存储具体的数据(文本、数字、公式、布尔值等),并可设置样式。
- POI 实现类:
XSSFCell:.xlsx文件的单元格。- 注意:单元格对象可能为
null(表示该位置无数据)。
如图:

层级关系示例
一个 Excel 文件的结构可理解为:
students.xlsx(Workbook) → "学生信息表"(Sheet) → 第 0 行(Row 0:表头行) → 第 0 列单元格(Cell 0:"学号")、第 1 列单元格(Cell 1:"姓名")......
三、实现
1、引入依赖
最新版本可参考Apache POI 官网
xml
<!-- 核心POI库 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.5</version>
</dependency>
<!-- 处理XSSF (.xlsx) -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.5</version>
</dependency>
<!-- 可选:处理公式 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>4.1.2</version>
</dependency>
<!-- 可选:XML解析依赖 -->
<dependency>
<groupId>org.apache.xmlbeans</groupId>
<artifactId>xmlbeans</artifactId>
<version>5.1.1</version>
</dependency>
Apache POI 版本与 JDK 对应表:
| Apache POI 版本 | 最低 JDK 版本 | 推荐 JDK 版本 | 备注 |
|---|---|---|---|
| 3.x 系列(如 3.17、3.19) | JDK 6 | JDK 6/7/8 | 兼容老项目,已停止维护 |
| 4.x 系列(如 4.1.2、4.2.2) | JDK 8 | JDK 8/11 | 主流稳定版本,兼容大部分场景 |
| 5.x 系列(如 5.2.0、5.2.5) | JDK 11 | JDK 11/17 | 最新特性支持,推荐 JDK 11+ |
| 5.2.3+ | JDK 11 | JDK 11/17/21 | 适配更高版本 JDK,支持模块化 |
2、基础操作:创建.xlsx 文件
简单创建工作簿、工作表、行和单元格
java
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFCell;
import java.io.FileOutputStream;
import java.io.IOException;
public class CreateXlsxExample {
public static void main(String[] args) {
// 1. 创建工作簿
XSSFWorkbook workbook = new XSSFWorkbook();
// 2. 创建工作表(指定名称)
XSSFSheet sheet = workbook.createSheet("学生信息表");
// 3. 创建行(行索引从0开始)
XSSFRow headerRow = sheet.createRow(0); // 表头行
// 4. 创建单元格并设置值(列索引从0开始)
XSSFCell cell0 = headerRow.createCell(0);
cell0.setCellValue("学号");
XSSFCell cell1 = headerRow.createCell(1);
cell1.setCellValue("姓名");
XSSFCell cell2 = headerRow.createCell(2);
cell2.setCellValue("年龄");
// 5. 创建数据行
XSSFRow dataRow = sheet.createRow(1);
dataRow.createCell(0).setCellValue(1001);
dataRow.createCell(1).setCellValue("张三");
dataRow.createCell(2).setCellValue(20);
// 6. 自动调整列宽
sheet.autoSizeColumn(0);
sheet.autoSizeColumn(1);
sheet.autoSizeColumn(2);
// 7. 写入文件
try (FileOutputStream outputStream = new FileOutputStream("students.xlsx")) {
workbook.write(outputStream);
System.out.println("xlsx文件创建成功!");
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭工作簿
try {
workbook.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3、读取.xlsx 文件
读取单元格值(区分数据类型)
java
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.ss.usermodel.CellType;
import java.io.FileInputStream;
import java.io.IOException;
public class ReadXlsxExample {
public static void main(String[] args) {
try (FileInputStream inputStream = new FileInputStream("students.xlsx");
XSSFWorkbook workbook = new XSSFWorkbook(inputStream)) {
// 1. 获取工作表(通过名称或索引)
XSSFSheet sheet = workbook.getSheet("学生信息表");
// XSSFSheet sheet = workbook.getSheetAt(0); // 通过索引(0开始)
// 2. 遍历行
for (int rowNum = 0; rowNum <= sheet.getLastRowNum(); rowNum++) {
XSSFRow row = sheet.getRow(rowNum);
if (row == null) continue; // 跳过空行
// 3. 遍历单元格
for (int cellNum = 0; cellNum < row.getLastCellNum(); cellNum++) {
XSSFCell cell = row.getCell(cellNum);
if (cell == null) continue; // 跳空单元格
// 4. 根据单元格类型读取值
String cellValue = switch (cell.getCellType()) {
case STRING -> cell.getStringCellValue();
case NUMERIC -> String.valueOf(cell.getNumericCellValue());
case BOOLEAN -> String.valueOf(cell.getBooleanCellValue());
case FORMULA -> cell.getCellFormula(); // 公式
default -> "";
};
System.out.print(cellValue + "\t");
}
System.out.println();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
4、进阶操作:设置单元格样式
设置字体、对齐方式、背景色
java
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import java.io.FileOutputStream;
import java.io.IOException;
public class StyleXlsxExample {
public static void main(String[] args) {
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet sheet = workbook.createSheet("样式示例");
// 1. 创建字体样式
XSSFFont font = workbook.createFont();
font.setFontName("宋体");
font.setFontHeightInPoints((short) 12);
font.setBold(true); // 加粗
font.setColor(IndexedColors.RED.getIndex()); // 红色
// 2. 创建单元格样式
XSSFCellStyle style = workbook.createCellStyle();
style.setFont(font);
style.setAlignment(HorizontalAlignment.CENTER); // 水平居中
style.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中
style.setFillForegroundColor(IndexedColors.LIGHT_YELLOW.getIndex()); // 背景色
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
// 3. 应用样式到单元格
XSSFRow row = sheet.createRow(0);
XSSFCell cell = row.createCell(0);
cell.setCellValue("带样式的单元格");
cell.setCellStyle(style);
// 写入文件
try (FileOutputStream outputStream = new FileOutputStream("styled.xlsx")) {
workbook.write(outputStream);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
workbook.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
5、其他常用功能
合并单元格
java
// 合并第一行第0列到第2列的单元格
CellRangeAddress mergedRegion = new CellRangeAddress(0, 0, 0, 2);
sheet.addMergedRegion(mergedRegion);
设置单元格数据类型
java
XSSFCell cell = row.createCell(0);
cell.setCellType(CellType.NUMERIC); // 数值型
cell.setCellValue(99.9);
XSSFCell cell2 = row.createCell(1);
cell2.setCellType(CellType.BOOLEAN); // 布尔型
cell2.setCellValue(true);
写入公式
java
XSSFCell formulaCell = row.createCell(3);
formulaCell.setCellFormula("SUM(A2:C2)"); // 求和公式
四、注意
- 内存占用 :XSSF 处理大文件时(如 10 万行以上)会占用大量内存,建议使用SXSSF(Streaming XSSF)进行大数据量处理(SXSSF 通过临时文件缓存数据,降低内存占用)。
- 单元格索引 :行和列的索引均从0开始。
- 空行 / 空单元格处理 :
getRow(rowNum)或getCell(cellNum)可能返回null,需判空避免空指针。 - 文件关闭 :必须通过
workbook.close()关闭工作簿,释放资源;使用 try-with-resources 语法自动关闭流。
SXSSF(大数据量处理)示例
java
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.streaming.SXSSFSheet;
public class BigDataXlsxExample {
public static void main(String[] args) {
// SXSSFWorkbook(100):保留100行在内存,超过则写入临时文件
SXSSFWorkbook workbook = new SXSSFWorkbook(100);
SXSSFSheet sheet = workbook.createSheet("大数据表");
// 写入10万行数据
for (int i = 0; i < 100000; i++) {
XSSFRow row = sheet.createRow(i);
row.createCell(0).setCellValue("数据" + i);
row.createCell(1).setCellValue(i);
}
try (FileOutputStream outputStream = new FileOutputStream("bigdata.xlsx")) {
workbook.write(outputStream);
} catch (IOException e) {
e.printStackTrace();
} finally {
workbook.dispose(); // 清除临时文件
try {
workbook.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
五、总结
Apache POI 处理.xlsx文件(XSSF/SXSSF)的常用方法按照工作簿、工作表、行、单元格、样式、高级操作分类总结:
1、工作簿(Workbook)相关方法
| 方法 | 说明 |
|---|---|
new XSSFWorkbook() |
创建新的.xlsx工作簿 |
new XSSFWorkbook(InputStream) |
从输入流读取已存在的工作簿 |
new SXSSFWorkbook(int rowAccessWindowSize) |
创建支持大数据量的 SXSSF 工作簿(指定内存缓存行数) |
workbook.createSheet(String sheetName) |
创建指定名称的工作表 |
workbook.getSheet(String sheetName) |
通过名称获取工作表 |
workbook.getSheetAt(int index) |
通过索引(从 0 开始)获取工作表 |
workbook.removeSheetAt(int index) |
删除指定索引的工作表 |
workbook.write(OutputStream) |
将工作簿写入输出流(文件 / 网络) |
workbook.close() |
关闭工作簿,释放资源 |
sxssfWorkbook.dispose() |
SXSSF 专用:清除临时文件,释放磁盘空间 |
2、工作表(Sheet)相关
| 方法 | 说明 |
|---|---|
sheet.createRow(int rowNum) |
创建指定行号的行(行号从 0 开始) |
sheet.getRow(int rowNum) |
获取指定行号的行(不存在返回null) |
sheet.getLastRowNum() |
获取最后一行的行号(无数据行返回 - 1) |
sheet.autoSizeColumn(int columnIndex) |
自动调整指定列的宽度 |
sheet.setColumnWidth(int columnIndex, int width) |
设置列宽(单位:1/256 个字符宽度) |
sheet.addMergedRegion(CellRangeAddress) |
合并单元格(如new CellRangeAddress(0,0,0,2)表示合并第 0 行 0-2 列) |
sheet.removeMergedRegion(int index) |
移除指定索引的合并单元格区域 |
sheet.setDefaultRowHeight(short height) |
设置默认行高(单位:1/20 个点) |
3、行(Row)相关
| 方法 | 说明 |
|---|---|
row.createCell(int columnIndex) |
创建指定列号的单元格(列号从 0 开始) |
row.getCell(int columnIndex) |
获取指定列号的单元格(不存在返回null) |
row.getLastCellNum() |
获取最后一列的列号(无单元格返回 - 1) |
row.setRowNum(int rowNum) |
设置行号 |
row.setHeight(short height) |
设置行高 |
row.removeCell(Cell cell) |
移除指定单元格 |
4、单元格(Cell)相关
| 方法 | 说明 |
|---|---|
cell.setCellValue(Object value) |
设置单元格值(支持 String/Number/Boolean/Date 等) |
cell.getCellType() |
获取单元格类型(如CellType.STRING/CellType.NUMERIC) |
cell.getStringCellValue() |
获取字符串类型单元格的值 |
cell.getNumericCellValue() |
获取数值类型单元格的值 |
cell.getBooleanCellValue() |
获取布尔类型单元格的值 |
cell.setCellFormula(String formula) |
设置单元格公式(如"SUM(A1:B1)") |
cell.getCellFormula() |
获取单元格公式 |
cell.setCellStyle(CellStyle style) |
应用样式到单元格 |
cell.setCellType(CellType type) |
设置单元格数据类型(如CellType.FORMULA) |
5、样式与格式相关
单元格样式(CellStyle)
| 方法 | 说明 |
|---|---|
workbook.createCellStyle() |
创建新的单元格样式 |
style.setFont(Font font) |
设置字体样式 |
style.setAlignment(HorizontalAlignment align) |
设置水平对齐(如HorizontalAlignment.CENTER) |
style.setVerticalAlignment(VerticalAlignment align) |
设置垂直对齐(如VerticalAlignment.CENTER) |
style.setFillForegroundColor(IndexedColors color) |
设置背景色(需配合填充模式) |
style.setFillPattern(FillPatternType pattern) |
设置填充模式(如FillPatternType.SOLID_FOREGROUND) |
style.setBorderTop(BorderStyle style) |
设置上边框样式(如BorderStyle.THIN) |
style.setTopBorderColor(IndexedColors color) |
设置上边框颜色 |
字体(Font)
| 方法 | 说明 |
|---|---|
workbook.createFont() |
创建新字体 |
font.setFontName(String name) |
设置字体名称(如 "宋体""Arial") |
font.setFontHeightInPoints(short size) |
设置字体大小(单位:磅) |
font.setBold(boolean bold) |
设置加粗 |
font.setColor(IndexedColors color) |
设置字体颜色 |
font.setItalic(boolean italic) |
设置斜体 |
6、高级操作
| 方法 / 工具类 | 说明 |
|---|---|
CellRangeAddress.valueOf(String range) |
通过字符串(如 "A1:C3")创建单元格合并区域 |
DataFormatter.formatCellValue(Cell cell) |
格式化单元格值(按 Excel 显示格式输出,如日期、百分比) |
FormulaEvaluator.evaluate(Cell cell) |
计算公式单元格的结果(返回CellValue) |
sheet.setRowSumsBelow(boolean sumsBelow) |
设置汇总行位置(用于公式计算) |
核心操作逻辑
- 通过 Workbook 获取 Sheet;
- 通过 Sheet 获取 Row;
- 通过 Row 获取 Cell;
- 对 Cell 进行读写或样式设置。