使用 Apache POI + iText (最常用、免费、开源)
这是最经典和灵活的组合,适用于绝大多数场景,它完全免费,且对功能有完全的控制权。

- Apache POI: 用于读取和操作 Excel 文件。
- iText: 用于生成 PDF 文件。
核心思想:
- 使用 POI 加载 Excel 文件。
- 遍历 Excel 的每一个单元格,获取其内容(文本、数字、日期等)。
- 使用 iText 在 PDF 文档中创建相应的元素(段落、表格、单元格等),并将 Excel 的内容复制过去。
- 保存 PDF 文件。
优点:
- 完全免费: 无需任何商业许可。
- 功能强大: 可以对 PDF 的样式、布局进行精细控制。
- 灵活: 可以只转换特定的 Sheet、Row 或 Cell。
缺点:
- 代码复杂: 需要手动处理 Excel 到 PDF 的布局映射,代码量相对较大。
- 样式还原困难: 完美还原 Excel 中的复杂样式(如合并单元格、复杂边框、背景色、字体、旋转等)非常具有挑战性。
实现步骤
添加 Maven 依赖

在你的 pom.xml 文件中添加以下依赖:
<dependencies>
<!-- Apache POI for Excel -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.3</version>
</dependency>
<!-- iText for PDF -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13.3</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
</dependencies>
Java 代码示例
这个示例将一个简单的 Excel 文件转换为一个包含表格的 PDF 文件。
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import org.apache.poi.ss.usermodel.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class ExcelToPdfWithPOIAndIText {
public static void main(String[] args) {
String excelFilePath = "path/to/your/input.xlsx"; // 你的Excel文件路径
String pdfFilePath = "path/to/your/output.pdf"; // 输出的PDF文件路径
try {
convertExcelToPdf(excelFilePath, pdfFilePath);
System.out.println("转换成功!PDF 文件已保存至: " + pdfFilePath);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void convertExcelToPdf(String excelFilePath, String pdfFilePath) throws Exception {
// 1. 加载 Excel 文件
FileInputStream excelFile = new FileInputStream(new File(excelFilePath));
Workbook workbook = WorkbookFactory.create(excelFile);
// 2. 创建 PDF 文档
Document document = new Document(PageSize.A4);
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(pdfFilePath));
document.open();
// 3. 遍历 Excel 的每一个 Sheet
for (int sheetNum = 0; sheetNum < workbook.getNumberOfSheets(); sheetNum++) {
Sheet sheet = workbook.getSheetAt(sheetNum);
// 如果不是第一页,添加新的一页
if (sheetNum > 0) {
document.newPage();
}
// 4. 创建 PDF 表格 (列数从第一行获取)
Row firstRow = sheet.getRow(0);
int columnCount = (firstRow != null) ? firstRow.getPhysicalNumberOfCells() : 0;
PdfPTable pdfTable = new PdfPTable(columnCount);
// 5. 遍历 Sheet 的每一行
for (Row row : sheet) {
// 6. 遍历每一行的每一个单元格
for (Cell cell : row) {
PdfPCell pdfCell = new PdfPCell();
// 获取单元格内容并处理
switch (cell.getCellType()) {
case STRING:
pdfCell.addElement(new Paragraph(cell.getStringCellValue()));
break;
case NUMERIC:
// 处理日期
if (DateUtil.isCellDateFormatted(cell)) {
pdfCell.addElement(new Paragraph(cell.getDateCellValue().toString()));
} else {
pdfCell.addElement(new Paragraph(String.valueOf(cell.getNumericCellValue())));
}
break;
case BOOLEAN:
pdfCell.addElement(new Paragraph(String.valueOf(cell.getBooleanCellValue())));
break;
case FORMULA:
// 获取公式的计算结果
pdfCell.addElement(new Paragraph(cell.getCellFormula()));
break;
default:
pdfCell.addElement(new Paragraph(""));
}
// 设置单元格样式(简单示例)
pdfCell.setBorder(Rectangle.BOX);
pdfCell.setBorderWidth(1);
pdfTable.addCell(pdfCell);
}
}
document.add(pdfTable);
}
// 7. 关闭文档和 Excel 文件
document.close();
workbook.close();
excelFile.close();
}
}
使用商业库 (最简单、效果最好、需付费)
如果你追求开发效率和完美的样式还原,并且项目预算允许,使用商业库是最佳选择,这些库内部处理了所有复杂的布局和样式转换逻辑。
- Aspose.Cells: 功能极其强大的 Java Excel 和 PDF 组件,业界口碑很好。
- Spire.XLS: 另一款非常流行的商业组件,性能和效果同样出色。
核心思想: 只需几行代码,库会自动完成所有工作,包括样式、字体、图片、图表等。
优点:
- 极其简单: 通常只需 3-5 行代码。
- 高保真: 能完美还原 Excel 的所有样式和布局。
- 功能丰富: 支持转换、加密、签名、打印等多种高级功能。
缺点:
- 收费: 需要购买许可证,免费版本通常有功能或页数限制。
实现步骤 (以 Aspose.Cells 为例)
添加 Maven 依赖
Aspose 提供了官方的 Maven 仓库。
<dependencies>
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-cells</artifactId>
<version>23.8</version> <!-- 请使用最新版本 -->
</dependency>
</dependencies>
Java 代码示例
import com.aspose.cells.*;
public class ExcelToPdfWithAspose {
public static void main(String[] args) throws Exception {
// 设置 Aspose.Cells 的许可证(如果使用付费版)
// License license = new License();
// license.setLicense("Aspose.Cells.Java.lic");
String excelFilePath = "path/to/your/input.xlsx";
String pdfFilePath = "path/to/your/output.pdf";
// 1. 加载 Excel 工作簿
Workbook workbook = new Workbook(excelFilePath);
// 2. 创建 PdfSaveOptions 对象
PdfSaveOptions pdfSaveOptions = new PdfSaveOptions();
// (可选) 设置 PDF 保存选项,compliance, JPEG quality 等
// pdfSaveOptions.setCompliance(PdfCompliance.PDF_A_1_A);
// pdfSaveOptions.setJpegQuality(90);
// 3. 直接调用 save 方法,指定格式为 PDF
workbook.save(pdfFilePath, pdfSaveOptions);
System.out.println("转换成功!PDF 文件已保存至: " + pdfFilePath);
}
}
可以看到,使用 Aspose 的代码量非常少,而且转换效果是所有方法中最好的。
使用 OpenPDF (iText 的一个分支)
OpenPDF 是 iText 5 的一个分支,在 iText 宣布 AGPL 许可后,为了提供一个更友好的开源许可证而诞生,它的 API 与 iText 5 几乎完全相同。
优点:
- 免费开源: 拥有更宽松的 Apache 2.0 许可证。
- API 兼容: 如果你熟悉 iText 5,可以无缝迁移。
缺点:
- 与 POI + iText 组合的缺点相同:代码复杂,样式还原困难。
实现步骤:
与 方法一 几乎完全相同,只需将 Maven 依赖从 com.itextpdf 换成 com.lowagie。
<!-- OpenPDF 替代 iText -->
<dependency>
<groupId>com.github.librepdf</groupId>
<artifactId>openpdf</artifactId>
<version>1.3.30</version>
</dependency>
代码无需修改,因为包名和类名在早期版本中是兼容的。
使用 UNO (基于 LibreOffice/OpenOffice)
这种方法非常特殊,它通过 Java 启动一个 LibreOffice 或 OpenOffice 的进程,然后利用其内置的转换功能来完成。
核心思想:
- Java 代码通过 UNO (Universal Network Objects) 协议连接到一个正在运行的 LibreOffice 实例。
- 将 Excel 文件加载到 LibreOffice 中。
- 调用 LibreOffice 的 API,执行“另存为 PDF”的操作。
- 关闭连接。
优点:
- 转换质量高: 使用 LibreOffice 引擎,样式还原效果不错。
- 免费: LibreOffice 本身是免费的。
缺点:
- 依赖外部软件: 必须在服务器上安装并运行 LibreOffice 或 OpenOffice。
- 性能和稳定性问题: 启动外部进程会增加开销,且需要处理进程的生命周期,在生产环境中可能不稳定。
- 配置复杂: 需要配置 LibreOffice 的 headless 模式和端口。
适用场景: 通常用于桌面应用程序或一些特定的自动化脚本,不推荐用于高并发的 Web 服务器环境。
总结与如何选择
| 方法 | 优点 | 缺点 | 推荐场景 |
|---|---|---|---|
| POI + iText/OpenPDF | 完全免费、灵活、功能强大 | 代码复杂、样式还原困难、开发周期长 | 预算有限、对转换质量要求不高、需要精细控制转换过程、有足够开发时间的项目。 |
| 商业库 (Aspose/Spire) | 极其简单、高保真、功能丰富 | 收费 | 追求开发效率、对样式还原有严格要求、项目预算充足的企业级应用。 |
| UNO (LibreOffice) | 转换质量尚可、免费 | 依赖外部软件、性能不稳定、配置复杂 | 桌面应用、自动化脚本,或已有 LibreOffice 环境且无法安装其他库的环境。 |
给你的建议:
- 如果你是个人学习或小型项目,且预算为 0: 选择 方法一 (POI + iText/OpenPDF),虽然代码多,但能让你深入了解转换的原理。
- 如果你是商业项目,或对时间、质量有要求: 强烈推荐 方法二 (商业库),它能为你节省大量的开发和调试时间,避免因样式问题带来的客户投诉,通常这些库的投入是非常值得的。
- 如果你已经有一个运行中的 LibreOffice 环境: 可以尝试 方法四 (UNO) 作为一种备选方案,但务必先进行充分的性能和稳定性测试。
