关于 apache-poi
apache-poi 是面向使用 Apache POI 读写 Excel 工作簿的 Java 开发者的速查技能,重点介绍实用模式、资源与内存管理,以及常见表格问题排查。
主要功能
- 01创建并导出 Excel 工作簿
- 02复用单元格样式
- 03以流式方式写入大型工作簿
- 04通过事件解析读取大型文件
- 05诊断常见 Excel 与 POI 错误
适用场景
- 01根据应用数据生成 Excel 导出文件
- 02通过 REST 端点提供工作簿下载
- 03以较低内存占用处理大型表格
- 04解决单元格类型或格式问题
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ claude-dev-suite/ claude-dev-suite --skill apache-poi安装后在 Claude Code 中输入/apache-poi确认已加载。
详细介绍
Apache POI - 快速参考
何时不应使用此技能
- CSV 文件 - 处理 CSV 时使用 OpenCSV、Apache Commons CSV 或
Files.lines() - 生成 PDF - 改用 Apache PDFBox 或 iText
- 大型 Excel 文件(> 100k 行) - 使用
SXSSFWorkbook或考虑导出为 CSV - Excel 公式/宏 - POI 对宏的支持有限;可考虑 VBA 替代方案
- 实时编辑 Excel - POI 用于生成和解析,不用于协同编辑
深入了解:使用
mcp__documentation__fetch_docs,并将 technology 设置为:apache-poi,以获取完整的 API 文档、高级格式设置和公式处理说明。
核心模式
Maven
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.5</version>
</dependency>
创建 Excel
try (Workbook workbook = new XSSFWorkbook()) {
Sheet sheet = workbook.createSheet("Data");
// Header
Row header = sheet.createRow(0);
header.createCell(0).setCellValue("Name");
header.createCell(1).setCellValue("Email");
// Data
Row row = sheet.createRow(1);
row.createCell(0).setCellValue("John");
row.createCell(1).setCellValue("[email protected]");
// Auto-size
sheet.autoSizeColumn(0);
sheet.autoSizeColumn(1);
// Write
workbook.write(new FileOutputStream("output.xlsx"));
}
导出服务
@Service
public class ExportService {
public byte[] exportToExcel(List<User> users) throws IOException {
try (Workbook wb = new XSSFWorkbook();
ByteArrayOutputStream out = new ByteArrayOutputStream()) {
Sheet sheet = wb.createSheet("Users");
// ... populate rows
wb.write(out);
return out.toByteArray();
}
}
}
REST 下载端点
@GetMapping("/export")
public ResponseEntity<byte[]> export() throws IOException {
byte[] data = exportService.exportToExcel(users);
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=data.xlsx")
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(data);
}
单元格样式
CellStyle headerStyle = workbook.createCellStyle();
Font font = workbook.createFont();
font.setBold(true);
headerStyle.setFont(font);
cell.setCellStyle(headerStyle);
反模式
| 反模式 | 错误原因 | 正确做法 |
|---|---|---|
| 未关闭工作簿 | 内存泄漏、文件锁定 | 使用 try-with-resources:try (Workbook wb = new XSSFWorkbook()) |
| 在循环中创建样式 | 工作簿最多只能有 64,000 种样式 | 创建一次样式,并在各单元格间重复使用 |
对大型文件使用 XSSFWorkbook | 超过 100k 行时会出现 OutOfMemoryError | 使用 SXSSFWorkbook 进行流式写入 |
| 将整个文件读入内存 | 大型文件会耗尽内存 | 读取时使用基于事件的解析(SAX) |
| 未设置单元格类型 | 数据会被错误解读 | 显式设置单元格类型:cell.setCellType(CellType.NUMERIC) |
对每一列都使用 autoSizeColumn() | 速度很慢,尤其是行数较多时 | 手动设置列宽,或谨慎使用 |
| 硬编码列索引 | 脆弱,列变更时会出错 | 使用常量或列名映射 |
| 为大型数据集生成 Excel | Excel 最多支持 1M 行,且速度较慢 | 考虑改为导出 CSV 或数据库 |
快速故障排查
| 问题 | 诊断 | 解决方案 |
|---|---|---|
大型 Excel 文件导致 OutOfMemoryError | 使用了 XSSFWorkbook,所有数据都在内存中 | 改用 SXSSFWorkbook 进行流式处理 |
IllegalStateException: Cannot get a STRING value from a NUMERIC cell | 单元格类型读取器不匹配 | 读取前使用 cell.getCellType() 检查类型 |
| 生成后文件损坏 | 工作簿未正确关闭 | 使用 try-with-resources,或显式调用 wb.close() |
| 样式未生效 | 超出 64,000 种样式的限制 | 重复使用 CellStyle 对象,不要在循环中创建 |
| Excel 中的数字显示为文本 | 未设置单元格类型 | 使用 cell.setCellType(CellType.NUMERIC),并将值设置为数字 |
| 公式未计算 | 未设置公式模式 | 使用 cell.setCellFormula("SUM(A1:A10)"),或强制重新计算 |
| 生成速度很慢 | 在大型工作表上使用了 autoSizeColumn() | 移除该调用,或仅对关键列调用 |
| 日期格式不正确 | 默认格式不符合要求 | 使用自定义格式创建日期 CellStyle |
相关技能
参考资料
评论
支持 Markdown