Java 中导出 Excel 文件的方法
在 Java 中导出 Excel 文件的方法有多种,主要依赖不同的类库或工具,每种方法适用于不同的场景(如数据量大小、格式复杂度、易用性等)。以下是常见的几种实现方式:
选择建议
简单格式 + 小数据量:Apache POI(XSSF/HSSF)
或 EasyExcel
。
复杂格式 + 中大数据量:EasyExcel
(优先)或 POI
+ 自定义样式。
超大数据量(百万级):EasyExcel
(默认优化)或 POI
的 SXSSF
。
固定模板报表:Freemarker/Thymeleaf
模板引擎。
纯数据导出(无格式):CSV
格式。
其中,EasyExcel
因易用性和性能优势,成为目前 Java 导出 Excel 的主流选择,尤其在业务系统中广泛应用。
一、基于 Apache POI(最常用)
Apache POI 是 Apache 基金会的开源项目,是 Java 处理 Microsoft Office 文档(包括 Excel)的主流工具,支持.xls(Excel 97-2003)和.xlsx(Excel 2007+)格式。
核心类
HSSF
:处理 .xls 格式(最多 65536 行,适合小数据量)。
核心类:HSSFWorkbook(文档)、HSSFSheet(工作表)、HSSFRow(行)、HSSFCell(单元格)。
XSSF
:处理 .xlsx 格式(支持百万级行,适合中大数据量)。
核心类:XSSFWorkbook、XSSFSheet、XSSFRow、XSSFCell。
SXSSF
:XSSF的扩展,支持大数据量导出(通过内存优化,适合十万级以上数据,避免 OOM)。
优点
功能全面,支持复杂格式(单元格样式、合并单元格、公式、图表等)。
兼容性好,支持所有 Excel 版本。
缺点
代码相对繁琐,需要手动创建行、单元格并设置样式。
处理大数据时(如十万级以上),XSSF 可能占用较多内存(需用 SXSSF 优化)。
示例代码片段(XSSF)
// 创建.xlsx文档
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet sheet = workbook.createSheet("Sheet1");// 创建标题行
XSSFRow row = sheet.createRow(0);
row.createCell(0).setCellValue("姓名");
row.createCell(1).setCellValue("年龄");// 填充数据
XSSFRow dataRow = sheet.createRow(1);
dataRow.createCell(0).setCellValue("张三");
dataRow.createCell(1).setCellValue(25);// 输出到文件或响应流
FileOutputStream fos = new FileOutputStream("test.xlsx");
workbook.write(fos);
fos.close();
workbook.close();
二、基于 Alibaba EasyExcel
EasyExcel
是阿里巴巴开源的 Excel 处理工具,基于 POI 封装,专注于简化代码和优化大数据量性能,避免 POI 的内存占用问题。
核心特点
注解驱动:通过@ExcelProperty等注解映射 Java 对象与 Excel 列,无需手动创建单元格。
低内存:默认采用 SXSSF 的内存优化机制,支持百万级数据导出。
支持复杂格式:合并单元格、表头样式、自定义转换器等。
优点
代码简洁,无需手动处理行和单元格,降低开发成本。
性能优异,适合大数据量导出(如报表、日志数据)。
缺点
高级格式(如公式、图表)支持较弱,复杂场景仍需结合 POI。
示例代码片段
// 定义数据模型(通过注解映射Excel列)
@Data
public class User {@ExcelProperty("姓名")private String name;@ExcelProperty("年龄")private Integer age;
}// 导出逻辑
List<User> data = new ArrayList<>();
data.add(new User("卡布大帝", 25));// 输出到文件
EasyExcel.write("test_easy.xlsx", User.class).sheet("Sheet1").doWrite(data);
三、基于 JXL(仅支持.xls)
JXL(Java Excel API) 是早期的 Excel 处理工具,仅支持 .xls 格式(不支持.xlsx),目前已停止维护,逐渐被 POI 替代。
优点
轻量级,API 简单,适合简单的.xls 文件导出。
缺点
不支持.xlsx 格式,功能有限(如不支持公式、图表),且不再更新。
示例代码片段
// 创建.xls文档
WritableWorkbook workbook = Workbook.createWorkbook(new File("test_jxl.xls"));
WritableSheet sheet = workbook.createSheet("Sheet1", 0);// 标题行
Label nameLabel = new Label(0, 0, "姓名");
Label ageLabel = new Label(1, 0, "年龄");
sheet.addCell(nameLabel);
sheet.addCell(ageLabel);// 数据行
Label name = new Label(0, 1, "张三");
Number age = new Number(1, 1, 25);
sheet.addCell(name);
sheet.addCell(age);workbook.write();
workbook.close();
四、基于模板引擎(如 Freemarker、Thymeleaf)
通过Excel 模板(如.xlsx模板)结合模板引擎,动态填充数据后导出。适用于格式固定、样式复杂的报表(如财务报表、合同模板)。
原理
准备 Excel 模板,用占位符(如${name})标记需要填充的位置。
用模板引擎解析模板,替换占位符为实际数据。
生成最终 Excel 文件。
优点
样式与逻辑分离,模板可由非开发人员(如运营)维护。
适合复杂格式报表,无需代码中手动设置样式。
缺点
灵活性较低,模板变更需同步更新占位符。
大数据量场景性能较差。
示例(Freemarker)
模板文件(template.xlsx.ftl)中单元格设置为 ${user.name}。
代码填充数据:
Configuration cfg = new Configuration(Configuration.VERSION_2_3_31);
cfg.setDirectoryForTemplateLoading(new File("templates"));
Template template = cfg.getTemplate("template.xlsx.ftl");Map<String, Object> data = new HashMap<>();
data.put("user", new User("张三", 25));FileOutputStream fos = new FileOutputStream("report.xlsx");
template.process(data, new OutputStreamWriter(fos));
fos.close();
五、基于 CSV 格式(伪 Excel)
CSV(逗号分隔值)是一种简单的文本格式,可被 Excel 直接打开,适合纯数据导出(无格式要求)。
优点
实现简单,无需依赖任何 Excel 类库。
生成速度快,适合超大数据量(如千万级)。
缺点
不支持任何样式(如单元格合并、颜色、公式),仅能存储纯文本数据。
示例代码片段
FileWriter writer = new FileWriter("data.csv");
// 标题行
writer.write("姓名,年龄\n");
// 数据行
writer.write("张三,25\n");
writer.write("李四,30\n");
writer.close();
六、其他工具
Alibaba EasyExcel
:如前文所述,是 POI 的优化封装,推荐优先使用。
Aspose.Cells
:商业工具,功能强大(支持所有 Excel 特性),但需要付费授权,适合企业级复杂场景。
JXLS
:结合 POI 和模板引擎,通过标签(如jx:each)在 Excel 模板中循环填充数据,适合动态报表。