下面我将从最简单的例子开始,逐步介绍更复杂的场景,并提供完整的代码示例。

准备工作:添加 POI 依赖
你需要在你的项目中添加 Apache POI 的依赖,如果你使用 Maven,在 pom.xml 文件中添加以下依赖:
<dependencies>
<!-- 核心库 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.5</version> <!-- 建议使用最新稳定版 -->
</dependency>
<!-- 用于处理 .xlsx 格式 (OOXML) -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.5</version>
</dependency>
<!-- 为了更好的性能,特别是处理大文件时,建议添加这个 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>5.2.5</version>
</dependency>
</dependencies>
如果你使用 Gradle,在 build.gradle 文件中添加:
implementation 'org.apache.poi:poi:5.2.5' implementation 'org.apache.poi:poi-ooxml:5.2.5' implementation 'org.apache.poi:poi-scratchpad:5.2.5'
示例 1:最简单的写入 - 创建一个 .xlsx 文件并写入数据
这个例子将创建一个名为 simple.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. 创建一个新的 XSSFWorkbook 对象,代表一个 .xlsx 文件
Workbook workbook = new XSSFWorkbook();
try (FileOutputStream fileOut = new FileOutputStream("simple.xlsx")) {
// 2. 在工作簿中创建一个新的工作表
Sheet sheet = workbook.createSheet("员工信息");
// 3. 创建一行(行号从0开始)
Row headerRow = sheet.createRow(0);
// 4. 在行中创建单元格并设置值
Cell cell1 = headerRow.createCell(0);
cell1.setCellValue("姓名");
Cell cell2 = headerRow.createCell(1);
cell2.setCellValue("年龄");
Cell cell3 = headerRow.createCell(2);
cell3.setCellValue("部门");
// 创建第二行,写入数据
Row dataRow = sheet.createRow(1);
dataRow.createCell(0).setCellValue("张三");
dataRow.createCell(1).setCellValue(30);
dataRow.createCell(2).setCellValue("技术部");
// 5. 将工作簿写入到文件输出流
workbook.write(fileOut);
System.out.println("Excel 文件 simple.xlsx 创建成功!");
} catch (IOException e) {
e.printStackTrace();
} finally {
// 6. 关闭工作簿,释放资源
try {
if (workbook != null) {
workbook.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
代码解释:

Workbook workbook = new XSSFWorkbook();: 创建一个代表.xlsx文件的工作簿,如果需要创建.xls文件,则使用new HSSFWorkbook()。Sheet sheet = workbook.createSheet("员工信息");: 在工作簿中创建一个名为 "员工信息" 的工作表。Row headerRow = sheet.createRow(0);: 创建第一行(索引为0)。Cell cell1 = headerRow.createCell(0);: 在第一行创建第一个单元格(索引为0)。cell1.setCellValue("姓名");: 为单元格设置字符串值。workbook.write(fileOut);: 将内存中的Workbook对象内容写入到指定的文件中。workbook.close(): 非常重要! 在finally块中关闭Workbook,以释放系统资源。
示例 2:写入不同类型的数据
Excel 支持多种数据类型,POI 也提供了相应的方法。
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
public class DifferentDataTypeWrite {
public static void main(String[] args) {
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet("数据类型示例");
Row row = sheet.createRow(0);
// 字符串
row.createCell(0).setCellValue("这是字符串");
// 数字
row.createCell(1).setCellValue(12345.6789);
// 布尔值
row.createCell(2).setCellValue(true);
// 日期
row.createCell(3).setCellValue(new Date());
// 公式
row.createCell(4).setCellValue("=SUM(1, 2)"); // 写入公式字符串
// 从 POI 3.15 开始,可以直接设置 Date 类型,但需要配合 CellStyle
// 否则 Excel 可能无法正确识别日期格式
CreationHelper createHelper = workbook.getCreationHelper();
CellStyle dateStyle = workbook.createCellStyle();
dateStyle.setDataFormat(createHelper.createDataFormat().getFormat("yyyy-MM-dd HH:mm:ss"));
Cell dateCell = row.createCell(5);
dateCell.setCellValue(new Date());
dateCell.setCellStyle(dateStyle);
try (FileOutputStream fileOut = new FileOutputStream("data_types.xlsx")) {
workbook.write(fileOut);
System.out.println("Excel 文件 data_types.xlsx 创建成功!");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (workbook != null) workbook.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
示例 3:设置样式(字体、颜色、边框)
使用 CellStyle 可以让你的 Excel 表格更美观。
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) {
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet("样式示例");
// 创建一个样式对象
CellStyle style = workbook.createCellStyle();
// 1. 设置字体
Font font = workbook.createFont();
font.setFontName("Arial");
font.setFontHeightInPoints((short) 14); // 字号
font.setBold(true); // 加粗
font.setColor(IndexedColors.RED.getIndex()); // 字体颜色
style.setFont(font);
// 2. 设置背景色
style.setFillForegroundColor(IndexedColors.LIGHT_CORNFLOWER_BLUE.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
// 3. 设置边框
style.setBorderTop(BorderStyle.THIN);
style.setBorderBottom(BorderStyle.THIN);
style.setBorderLeft(BorderStyle.THIN);
style.setBorderRight(BorderStyle.THIN);
// 4. 设置对齐方式
style.setAlignment(HorizontalAlignment.CENTER); // 水平居中
style.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中
// 创建行和单元格
Row row = sheet.createRow(2);
Cell cell = row.createCell(1);
cell.setCellValue("这是一个应用了样式的单元格");
// 将样式应用到单元格
cell.setCellStyle(style);
try (FileOutputStream fileOut = new FileOutputStream("styled.xlsx")) {
workbook.write(fileOut);
System.out.println("Excel 文件 styled.xlsx 创建成功!");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (workbook != null) workbook.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
示例 4:自动调整列宽
当写入的文本内容过长时,可以自动调整列宽以适应内容。
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileOutputStream;
import java.io.IOException;
public class AutoSizedColumnWrite {
public static void main(String[] args) {
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet("自动列宽");
Row row = sheet.createRow(0);
row.createCell(0).setCellValue("这是一个非常非常长的文本内容,用来测试自动调整列宽的功能是否正常工作。");
// 在写入所有数据后,遍历所有列并自动调整宽度
for (int i = 0; i < sheet.getRow(0).getLastCellNum(); i++) {
// autoSizeColumn 会根据内容计算最佳宽度
sheet.autoSizeColumn(i);
}
try (FileOutputStream fileOut = new FileOutputStream("auto_size.xlsx")) {
workbook.write(fileOut);
System.out.println("Excel 文件 auto_size.xlsx 创建成功!");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (workbook != null) workbook.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
示例 5:合并单元格
使用 Sheet.addMergedRegion() 方法可以合并单元格。

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileOutputStream;
import java.io.IOException;
public class MergedCellsWrite {
public static void main(String[] args) {
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet("合并单元格");
// 创建一个样式用于合并后的标题
CellStyle style = workbook.createCellStyle();
Font font = workbook.createFont();
font.setFontHeightInPoints((short) 16);
font.setBold(true);
style.setFont(font);
style.setAlignment(HorizontalAlignment.CENTER);
Row row = sheet.createRow(0);
Cell cell = row.createCell(0);
cell.setCellValue("合并单元格示例");
cell.setCellStyle(style);
// 参数:起始行, 结束行, 起始列, 结束列
// 合并第1行的第1列到第3列
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 2));
// 在合并后的单元格下方写入数据
Row dataRow1 = sheet.createRow(1);
dataRow1.createCell(0).setCellValue("姓名");
dataRow1.createCell(1).setCellValue("年龄");
dataRow1.createCell(2).setCellValue("城市");
try (FileOutputStream fileOut = new FileOutputStream("merged_cells.xlsx")) {
workbook.write(fileOut);
System.out.println("Excel 文件 merged_cells.xlsx 创建成功!");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (workbook != null) workbook.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
总结与最佳实践
-
选择正确的 Workbook 类型:
.xlsx(新版): 使用XSSFWorkbook,推荐使用,因为它基于 XML,功能更现代。.xls(旧版): 使用HSSFWorkbook,兼容性好,但有行数和列数的限制(65536行,256列)。
-
资源管理:
- 务必关闭
Workbook和FileOutputStream,使用try-with-resources语句是最佳实践,它可以自动关闭实现了AutoCloseable接口的对象(如FileOutputStream和Workbook)。
- 务必关闭
-
性能优化 (大文件):
- 如果要写入非常大的 Excel 文件(例如超过 50,000 行),使用
XSSFWorkbook会消耗大量内存。 - 应使用 SXSSFWorkbook (Streaming Usermodel),它只会将一部分数据保存在内存中,其余数据会临时写入磁盘,从而大大减少内存消耗。
- 注意:
SXSSFWorkbook是.xlsx格式的,并且它只支持写操作,不支持后续的读或修改。
// SXSSFWorkbook 示例 Workbook workbook = new SXSSFWorkbook(100); // 在内存中保留100行,其余写入磁盘 // ... 其他写入操作 ... ((SXSSFWorkbook)workbook).dispose(); // 清理临时文件
- 如果要写入非常大的 Excel 文件(例如超过 50,000 行),使用
-
样式复用:
- 如果多个单元格需要应用相同的样式,请创建一个
CellStyle对象并重复使用它,而不是为每个单元格都创建一个新的,这样可以显著提高性能并减少内存占用。
- 如果多个单元格需要应用相同的样式,请创建一个
希望这些示例能帮助你掌握使用 Java POI 写入 Excel 的基本方法!
