一、POI 是什么?
Apache POI 是 Apache 基金会提供的一套 Java 操作 Office 文档的开源库,主要支持:
- Excel(.xls / .xlsx)
- Word(.doc / .docx)
- PowerPoint
- Visio
- Outlook
其中最常用的就是 Excel 操作。
二、为什么要用 POI?
因为在企业开发中,Excel 是最常见的数据交换格式,比如:
- 导出报表(订单报表、财务报表)
- 导入数据(批量导入用户、批量导入商品)
- 模板导出(固定模板 + 动态数据)
- 数据备份
- 批量生成合同、发票等文档
而 Java 本身没有提供操作 Excel 的能力,所以必须依赖 POI。
三、POI 支持的 Excel 格式
POI 支持两种 Excel 格式:
-
HSSF ------ 操作
.xls(Excel 97-2003)- 最多 65536 行
- 最多 256 列
-
XSSF ------ 操作
.xlsx(Excel 2007+)- 最多 1,048,576 行
- 最多 16,384 列
- 推荐使用
-
SXSSF ------ 大数据量导出(百万级)
- 基于 XSSF,但使用 流式处理
- 适合导出几十万、几百万行数据
- 内存占用极低
四、POI 核心对象模型
POI 操作 Excel 的核心对象如下(非常重要):
- Workbook(工作簿) → 对应整个 Excel 文件 ,创建 / 读取 Excel 的入口对象
- XSSF 格式:
XSSFWorkbook workbook = new XSSFWorkbook();- Sheet(工作表) → 对应 Excel 里的一个 sheet 页签 ,一个 Workbook 可以创建多个 Sheet
- 创建:
Sheet sheet = workbook.createSheet("用户报表");- 获取:
Sheet sheet = workbook.getSheetAt(0);// 获取第一个 sheet- Row(行) → 对应 Sheet 中的一行数据 ,行索引从
0开始(0 是表头行)
- 创建:
Row row = sheet.createRow(0);// 创建第 1 行- 获取:
Row row = sheet.getRow(1);// 获取第 2 行- Cell(单元格) → 对应 Row 中的一个单元格 ,列索引从
0开始
- 创建:
Cell cell = row.createCell(0);// 创建当前行的第 1 列单元格- 获取:
Cell cell = row.getCell(1);// 获取当前行的第 2 列单元格- 辅助对象:
CellStyle(单元格样式)、Font(字体样式)→ 用于设置单元格的字体、颜色、对齐方式、边框等- 核心层级关系:
Workbook → Sheet → Row → Cell
五、POI 读写 Excel 实战
引入依赖:
java
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
写入 Excel(导出)
java
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileOutputStream;
import java.io.IOException;
public class ExcelWriter {
public static void main(String[] args) throws IOException {
// 1. 创建 Workbook
Workbook workbook = new XSSFWorkbook();
// 2. 创建 Sheet
Sheet sheet = workbook.createSheet("用户列表");
// 3. 创建表头行
Row headerRow = sheet.createRow(0);
headerRow.createCell(0).setCellValue("ID");
headerRow.createCell(1).setCellValue("姓名");
headerRow.createCell(2).setCellValue("年龄");
// 4. 写入数据
Object[][] data = {
{1, "张三", 20},
{2, "李四", 22},
{3, "王五", 25}
};
int rowIndex = 1;
for (Object[] rowData : data) {
Row row = sheet.createRow(rowIndex++);
row.createCell(0).setCellValue((Integer) rowData[0]);
row.createCell(1).setCellValue((String) rowData[1]);
row.createCell(2).setCellValue((Integer) rowData[2]);
}
// 5. 输出到文件
try (FileOutputStream outputStream = new FileOutputStream("users.xlsx")) {
workbook.write(outputStream);
}
System.out.println("Excel 生成成功!");
}
}
读取 Excel(导入)
java
import org.apache.poi.ss.usermodel.*;
import java.io.FileInputStream;
import java.io.IOException;
public class ExcelReader {
public static void main(String[] args) throws IOException {
// 1. 读取文件
try (FileInputStream inputStream = new FileInputStream("users.xlsx");
Workbook workbook = new XSSFWorkbook(inputStream)) {
// 2. 获取 Sheet
Sheet sheet = workbook.getSheetAt(0);
// 3. 遍历行
for (Row row : sheet) {
// 4. 遍历单元格
for (Cell cell : row) {
// 根据单元格类型读取数据
switch (cell.getCellType()) {
case STRING:
System.out.print(cell.getStringCellValue() + "\t");
break;
case NUMERIC:
System.out.print(cell.getNumericCellValue() + "\t");
break;
case BOOLEAN:
System.out.print(cell.getBooleanCellValue() + "\t");
break;
default:
System.out.print("\t");
}
}
System.out.println();
}
}
}
}