- Apache POI:功能最强大、历史最悠久、社区最活跃的 Java API,可以处理
.xls(旧版 Excel) 和.xlsx(新版 Excel) 格式,它是事实上的标准。 - EasyExcel:由阿里巴巴开源,基于 POI 封装,它的最大特点是内存占用低,特别适合处理大数据量(如十万甚至百万行数据)的导出,能有效避免
OutOfMemoryError。
下面我将详细介绍这两种方法,并提供从简单到复杂的完整代码示例。

Apache POI (功能全面,适合大多数场景)
Apache POI 是一个老牌项目,功能非常完善,可以操作 Office 文档的所有元素,包括样式、图表、图片、公式等。
添加 Maven 依赖
在你的 pom.xml 文件中添加 POI 的依赖,为了同时支持 .xls 和 .xlsx,建议都加上。
<dependencies>
<!-- 支持 .xlsx 格式 (Office 2007+) -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.5</version> <!-- 请使用最新版本 -->
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.5</version>
</dependency>
<!-- 支持 .xls 格式 (Office 97-2003) -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>5.2.5</version>
</dependency>
</dependencies>
代码示例
示例 1:最简单的导出(无样式)
这个例子演示如何创建一个 .xlsx 文件并写入数据。
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileOutputStream;
import java.io.IOException;
public class PoiSimpleExport {
public static void main(String[] args) {
// 1. 创建一个新的 Excel 工作簿 (XSSFWorkbook for .xlsx)
Workbook workbook = new XSSFWorkbook();
// 2. 创建一个工作表
Sheet sheet = workbook.createSheet("员工信息");
// 3. 创建表头(第一行)
Row headerRow = sheet.createRow(0);
headerRow.createCell(0).setCellValue("姓名");
headerRow.createCell(1).setCellValue("年龄");
headerRow.createCell(2).setCellValue("部门");
// 4. 创建数据行
Row dataRow1 = sheet.createRow(1);
dataRow1.createCell(0).setCellValue("张三");
dataRow1.createCell(1).setCellValue(28);
dataRow1.createCell(2).setCellValue("技术部");
Row dataRow2 = sheet.createRow(2);
dataRow2.createCell(0).setCellValue("李四");
dataRow2.createCell(1).setCellValue(32);
dataRow2.createCell(2).setCellValue("市场部");
// 5. 自动调整列宽,使内容能够完整显示
sheet.autoSizeColumn(0);
sheet.autoSizeColumn(1);
sheet.autoSizeColumn(2);
// 6. 写入文件
try (FileOutputStream outputStream = new FileOutputStream("D:/temp/员工信息.xlsx")) {
workbook.write(outputStream);
System.out.println("Excel 文件生成成功!");
} catch (IOException e) {
e.printStackTrace();
} finally {
// 7. 关闭工作簿
try {
workbook.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
示例 2:带样式的导出
这个例子演示如何设置单元格的样式,如字体、颜色、边框等。

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileOutputStream;
import java.io.IOException;
public class PoiStyledExport {
public static void main(String[] args) {
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet(" styled_sheet");
// 创建样式
CellStyle headerStyle = workbook.createCellStyle();
Font headerFont = workbook.createFont();
headerFont.setBold(true); // 加粗
headerFont.setColor(IndexedColors.WHITE.getIndex()); // 白色字体
headerStyle.setFont(headerFont);
headerStyle.setFillForegroundColor(IndexedColors.BLUE.getIndex()); // 蓝色背景
headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
headerStyle.setAlignment(HorizontalAlignment.CENTER); // 居中
headerStyle.setBorderBottom(BorderStyle.THIN);
headerStyle.setBorderTop(BorderStyle.THIN);
headerStyle.setBorderLeft(BorderStyle.THIN);
headerStyle.setBorderRight(BorderStyle.THIN);
// 数据行样式
CellStyle dataStyle = workbook.createCellStyle();
dataStyle.setAlignment(HorizontalAlignment.CENTER);
dataStyle.setBorderBottom(BorderStyle.THIN);
dataStyle.setBorderTop(BorderStyle.THIN);
dataStyle.setBorderLeft(BorderStyle.THIN);
dataStyle.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(headerStyle);
}
// 创建数据行
Row dataRow1 = sheet.createRow(1);
dataRow1.createCell(0).setCellValue("王五");
dataRow1.createCell(1).setCellValue(30);
dataRow1.createCell(2).setCellValue("产品部");
dataRow1.createCell(3).setCellValue.setCellValue(new Date()); // 日期类型
for(int i=0; i<dataRow1.getLastCellNum(); i++) {
dataRow1.getCell(i).setCellStyle(dataStyle);
}
// 自动调整列宽
for (int i = 0; i < headers.length; i++) {
sheet.autoSizeColumn(i);
}
// 写入文件
try (FileOutputStream outputStream = new FileOutputStream("D:/temp/styled_employee.xlsx")) {
workbook.write(outputStream);
System.out.println("带样式的 Excel 文件生成成功!");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
workbook.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
EasyExcel (内存优化,适合大数据量)
EasyExcel 是阿里巴巴开源的,它通过 SAX (Simple API for XML) 模式来解析 Excel,写操作同样采用了流式写入,因此在写入大量数据时,它不会一次性将所有数据加载到内存中,从而极大地降低了内存消耗。
添加 Maven 依赖
<dependencies>
<!-- easyexcel 核心依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.3.2</version> <!-- 请使用最新版本 -->
</dependency>
</dependencies>
代码示例
EasyExcel 的使用模式更简洁,它通过一个监听器(WriteSheetHolder 等)来处理数据。
示例 1:最简单的导出
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class EasyExcelSimpleExport {
public static void main(String[] args) {
// 1. 准备数据
List<User> dataList = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
dataList.add(new User("用户" + i, 20 + i, "部门" + i, new Date()));
}
// 2. 写入文件
String fileName = "D:/temp/easyexcel_user.xlsx";
// EasyExcel.write(fileName, User.class).sheet("用户数据").doWrite(dataList);
// 更灵活的写法,可以自定义表头
EasyExcel.write(fileName)
.head(head()) // 自定义表头
.sheet("用户信息")
.doWrite(dataList);
System.out.println("EasyExcel 文件生成成功!");
}
// 自定义表头
private static List<List<String>> head() {
List<List<String>> list = new ArrayList<>();
List<String> head0 = new ArrayList<>();
head0.add("姓名");
list.add(head0);
List<String> head1 = new ArrayList<>();
head1.add("年龄");
list.add(head1);
List<String> head2 = new ArrayList<>();
head2.add("部门");
list.add(head2);
List<String> head3 = new ArrayList<>();
head3.add("入职日期");
list.add(head3);
return list;
}
// 数据模型类
public static class User {
@ExcelProperty("姓名") // 指定列名
private String name;
@ExcelProperty("年龄")
private Integer age;
@ExcelProperty("部门")
private String department;
@ExcelProperty("入职日期")
private Date date;
// 构造器、getter/setter 省略...
public User(String name, Integer age, String department, Date date) {
this.name = name;
this.age = age;
this.department = department;
this.date = date;
}
// 必须有无参构造器
public User() {}
public String getName() { return name; }
public Integer getAge() { return age; }
public String getDepartment() { return department; }
public Date getDate() { return date; }
}
}
示例 2:大数据量导出(核心优势)
EasyExcel 导出大数据量时,推荐使用 ExcelWriter 和 WriteSheet 的组合,并分批次写入数据。
import com.alibaba.excel.EasyExcel;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class EasyExcelBigDataExport {
public static void main(String[] args) {
String fileName = "D:/temp/easyexcel_big_data.xlsx";
// 1. 创建 ExcelWriter
EasyExcel.write(fileName, User.class).sheet("大数据").doWrite(() -> {
// 2. 使用回调函数分批次写入数据
// 模拟从数据库分页查询数据
for (int i = 0; i < 100000; i++) { // 假设有10万条数据
List<User> dataList = new ArrayList<>();
for (int j = 0; j < 1000; j++) { // 每次查询1000条
dataList.add(new User("用户" + (i * 1000 + j), 20 + (i * 1000 + j) % 50, "部门" + (i * 1000 + j) % 10, new Date()));
}
// 返回数据,EasyExcel 会自动写入
return dataList;
}
// 数据写完后返回 null
return null;
});
System.out.println("大数据量 Excel 文件生成成功!");
}
// User 类同上...
}
如何选择?
| 特性 | Apache POI | EasyExcel |
|---|---|---|
| 内存占用 | 较高,大数据量易 OOM |
极低,流式写入,适合大数据 |
| API 易用性 | 繁琐,需要手动管理样式、对象 | 简洁,注解驱动,API 更友好 |
| 功能完整性 | 非常强大,支持所有 Office 功能 | 功能覆盖大部分常见需求,复杂功能可能需要回退 POI |
| 学习曲线 | 陡峭 | 平缓 |
| 适用场景 | - 数据量不大(几千行) - 需要复杂的样式、图表、图片等 - 对兼容性要求极高 |
- 数据量巨大(万行以上) - 快速开发和部署 - 对内存敏感的应用 |
- 对于日常中小型数据导出,或者需要非常复杂格式的 Excel,Apache POI 是一个可靠的选择。
- 对于大型数据导出,或者希望项目更轻量、开发更高效,EasyExcel 是不二之选,它解决了 POI 在大数据场景下的最大痛点。
希望这个详细的指南能帮助你!

