准备工作:添加 POI 依赖
你需要在你的项目中添加 Apache POI 的依赖,如果你使用 Maven,请在 pom.xml 文件中添加以下依赖:

<dependencies>
<!-- POI Core 核心库 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.5</version> <!-- 建议使用最新稳定版 -->
</dependency>
<!-- POI OOXML 支持 .xlsx 格式 (推荐) -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.5</version>
</dependency>
<!-- 为了处理 XML 和其他格式,可能需要这个依赖 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>5.2.5</version>
</dependency>
</dependencies>
注意: POI 支持 .xls (Excel 97-2003) 和 .xlsx (Excel 2007+) 两种格式。.xlsx 格式是现代标准,推荐使用。
核心概念
在开始写代码前,需要了解几个核心类:
| 类名 | 作用 | 备注 |
|---|---|---|
Workbook |
代表整个 Excel 文件(工作簿)。 | 它是一个接口,具体实现类有 HSSFWorkbook (.xls) 和 XSSFWorkbook (.xlsx)。 |
Sheet |
代表工作簿中的一个工作表(Sheet)。 | "Sheet1", "Sheet2"。 |
Row |
代表工作表中的一行。 | 行号从 0 开始。 |
Cell |
代表一行中的一个单元格。 | 列号从 0 开始。 |
CellStyle |
定义单元格的样式(如字体、颜色、边框、对齐方式等)。 |
基本流程:
- 创建一个
Workbook对象。 - 在
Workbook中创建一个Sheet对象。 - 在
Sheet中创建一个或多个Row对象。 - 在
Row中创建一个或多个Cell对象。 - 向
Cell中设置值。 - 将
Workbook对象写入输出流(如文件输出流)。 - 关闭所有资源。
代码示例
示例 1:创建一个简单的 .xlsx 文件并写入数据
这个例子将创建一个名为 student_info.xlsx 的文件,并写入几行学生信息。

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileOutputStream;
import java.io.IOException;
public class SimpleExcelWrite {
public static void main(String[] args) {
// 1. 定义文件输出路径
String filePath = "D:/temp/student_info.xlsx";
// try-with-resources 语句会自动关闭资源
try (Workbook workbook = new XSSFWorkbook(); // 创建一个 .xlsx 格式的工作簿
FileOutputStream outputStream = new FileOutputStream(filePath)) {
// 2. 创建一个工作表,名为 "学生信息"
Sheet sheet = workbook.createSheet("学生信息");
// 3. 创建表头(第一行)
Row headerRow = sheet.createRow(0);
headerRow.createCell(0).setCellValue("学号");
headerRow.createCell(1).setCellValue("姓名");
headerRow.createCell(2).setCellValue("年龄");
headerRow.createCell(3).setCellValue("专业");
// 4. 创建数据行
// 第二行
Row row1 = sheet.createRow(1);
row1.createCell(0).setCellValue(1001);
row1.createCell(1).setCellValue("张三");
row1.createCell(2).setCellValue(20);
row1.createCell(3).setCellValue("计算机科学");
// 第三行
Row row2 = sheet.createRow(2);
row2.createCell(0).setCellValue(1002);
row2.createCell(1).setCellValue("李四");
row2.createCell(2).setCellValue(21);
row2.createCell(3).setCellValue("软件工程");
// 第五行(故意跳过第四行,看看效果)
Row row3 = sheet.createRow(4);
row3.createCell(0).setCellValue(1003);
row3.createCell(1).setCellValue("王五");
row3.createCell(2).setCellValue(22);
row3.createCell(3).setCellValue("数据科学");
// 5. 将工作簿写入文件
workbook.write(outputStream);
System.out.println("Excel 文件创建成功!路径: " + filePath);
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行后,你会得到一个 student_info.xlsx 文件,内容如下:
| 学号 | 姓名 | 年龄 | 专业 |
| :--- | :--- | :--- | :--- |
| 1001 | 张三 | 20 | 计算机科学 |
| 1002 | 李四 | 21 | 软件工程 |
| (空行) | | | |
| 1003 | 王五 | 22 | 数据科学 |
示例 2:使用样式(字体、颜色、边框)
这个例子在示例1的基础上,为表头添加了样式,使其更醒目。
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileOutputStream;
import java.io.IOException;
public class StyledExcelWrite {
public static void main(String[] args) {
String filePath = "D:/temp/styled_student_info.xlsx";
try (Workbook workbook = new XSSFWorkbook();
FileOutputStream outputStream = new FileOutputStream(filePath)) {
Sheet sheet = workbook.createSheet("带样式的学生信息");
// --- 创建样式 ---
// 1. 创建一个字体样式
Font headerFont = workbook.createFont();
headerFont.setBold(true); // 加粗
headerFont.setFontHeightInPoints((short) 14); // 字体大小
headerFont.setColor(IndexedColors.RED.getIndex()); // 字体颜色
// 2. 创建一个单元格样式
CellStyle headerCellStyle = workbook.createCellStyle();
headerCellStyle.setFont(headerFont);
headerCellStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
headerCellStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中
// 设置边框
headerStyle.setBorderTop(BorderStyle.THIN);
headerStyle.setBorderBottom(BorderStyle.THIN);
headerStyle.setBorderLeft(BorderStyle.THIN);
headerStyle.setBorderRight(BorderStyle.THIN);
// --- 应用样式到表头 ---
Row headerRow = sheet.createRow(0);
String[] headers = {"学号", "姓名", "年龄", "专业"};
for (int i = 0; i < headers.length; i++) {
Cell cell = headerRow.createCell(i);
cell.setCellValue(headers[i]);
cell.setCellStyle(headerCellStyle);
}
// --- 写入数据行 ---
// 为了简单,这里只写一行数据
Row dataRow = sheet.createRow(1);
dataRow.createCell(0).setCellValue(1001);
dataRow.createCell(1).setCellValue("张三");
dataRow.createCell(2).setCellValue(20);
dataRow.createCell(3).setCellValue("计算机科学");
// --- 自动调整列宽 ---
for (int i = 0; i < headers.length; i++) {
sheet.autoSizeColumn(i);
}
workbook.write(outputStream);
System.out.println("带样式的 Excel 文件创建成功!路径: " + filePath);
} catch (IOException e) {
e.printStackTrace();
}
}
}
示例 3:写入大数据量(优化内存)
如果需要写入大量数据(例如数万行),直接使用 XSSFWorkbook 会导致内存溢出,因为它会将整个 Excel 文件加载到内存中,这时应该使用 SXSSFWorkbook,它是一个基于 XSSF 的流式 API,只在内存中保留一定数量的行,其他数据会临时写入磁盘,从而大大减少内存消耗。
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import java.io.FileOutputStream;
import java.io.IOException;
public class LargeDataExcelWrite {
public static void main(String[] args) {
String filePath = "D:/temp/large_data_report.xlsx";
// SXSSFWorkbook 的参数是内存中保留的行数,超过的会被写入临时文件
// -1 表示不限制,但会占用大量内存,1000 是一个比较合理的值。
try (Workbook workbook = new SXSSFWorkbook(1000);
FileOutputStream outputStream = new FileOutputStream(filePath)) {
Sheet sheet = workbook.createSheet("大数据报表");
// 假设有 10 万行数据
int rowCount = 100000;
for (int i = 0; i < rowCount; i++) {
Row row = sheet.createRow(i);
row.createCell(0).setCellValue("ID_" + i);
row.createCell(1).setCellValue("用户_" + i);
row.createCell(2).setCellValue(Math.random() * 10000); // 随机金额
// 每写 1000 行,可以调用一下 flush() 来清理内存(可选)
if (i % 1000 == 0) {
((SXSSFWorkbook) workbook).flushRows();
}
}
workbook.write(outputStream);
System.out.println("大数据量 Excel 文件创建成功!路径: " + filePath);
// 注意:SXSSFWorkbook 在关闭时会自动删除临时文件。
// 如果你需要保留临时文件,可以在构造时传入一个临时文件目录。
} catch (IOException e) {
e.printStackTrace();
}
}
}
最佳实践和注意事项
- 使用
try-with-resources:Workbook,FileOutputStream等资源都需要被关闭。try-with-resources语句可以确保它们在使用后被自动关闭,避免资源泄漏。 - 选择正确的
Workbook实现:.xls文件:HSSFWorkbook.xlsx文件:XSSFWorkbook(数据量小) 或SXSSFWorkbook(数据量大)
- 处理日期:POI 对日期有特殊处理。
- 写入时,使用
cell.setCellValue(new Date());。 - 必须为包含日期的单元格设置一个专门的日期格式样式,否则 Excel 可能无法正确识别。
CellStyle dateStyle = workbook.createCellStyle(); CreationHelper createHelper = workbook.getCreationHelper(); dateStyle.setDataFormat(createHelper.createDataFormat().getFormat("yyyy-MM-dd HH:mm:ss")); Cell dateCell = row.createCell(4); dateCell.setCellValue(new Date()); dateCell.setCellStyle(dateStyle);
- 写入时,使用
- 自动调整列宽:在写入所有数据后,调用
sheet.autoSizeColumn(columnIndex);可以根据内容自动调整列宽,使表格更美观,注意,这个方法在处理大数据量时可能会比较慢。 - 处理公式:和普通值一样,使用
cell.setFormula("A1+B1");来设置公式。 - 性能优化:
- 对于大数据量,务必使用
SXSSFWorkbook。 - 在循环中尽量避免重复创建样式和字体,最好在循环外创建好,然后在循环内复用。
- 对于大数据量,务必使用
希望这份详细的指南能帮助你熟练掌握使用 Java 和 POI 写入 Excel 文件!
