使用Apache POI将Excel转换为PDF:完整指南与最佳实践

一、为什么选择Apache POI?

Apache POI作为成熟的Java库,提供完整的Microsoft Office格式处理能力。其XSSFHSSF模块可分别处理Excel 2007+和早期版本,配合Apache PDFBox可实现高质量的PDF输出。

二、环境配置

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>5.2.3</version>
</dependency>
<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox</artifactId>
    <version>3.0.0</version>
</dependency>
<dependency>
    <groupId>fr.opensagres.xdocreport</groupId>
    <artifactId>fr.opensagres.poi.xwpf.converter.pdf</artifactId>
    <version>2.0.4</version>
</dependency>

三、基础转换实现

3.1 简单转换流程

  1. 使用XSSFWorkbook加载Excel文件
  2. 创建FileOutputStream输出流
  3. 调用Workbook.write()方法写入PDF

3.2 核心代码示例

public class ExcelToPdfConverter {
    public static void convert(String excelPath, String pdfPath) throws Exception {
        FileInputStream fis = new FileInputStream(excelPath);
        Workbook workbook = new XSSFWorkbook(fis);
        
        // 配置PDF转换器
        PrinterJob job = PrinterJob.getPrinterJob();
        job.setPrintable(workbook);
        
        // 设置PDF属性
        Book book = new PDFBook();
        book.setOrientation(PageFormat.LANDSCAPE);
        job.setJobName("Excel to PDF");
        
        // 执行转换
        FileOutputStream fos = new FileOutputStream(pdfPath);
        PDF pdf = new PDF(workbook, fos);
        pdf.setFitWidth(true);
        pdf.export();
        
        workbook.close();
    }
}

四、高级技巧与优化

4.1 页面设置控制

  • 分页符处理:通过sheet.setBreaks()调整分页
  • 页边距设置:使用sheet.setMargin()方法
  • 缩放比例:调整sheet.setZoom()参数

4.2 样式保留方案

Excel特性PDF实现方案
条件格式转为静态样式并添加注释
数据验证转换为PDF表单字段
图表对象先渲染为图片再嵌入

五、常见问题解决

5.1 中文乱码处理

配置字体映射:BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED)

5.2 大文件优化

  1. 使用SAX事件驱动模型解析
  2. 实施分块处理策略
  3. 启用内存缓存优化

六、完整案例演示

@Test
public void testExcelToPdfConversion() throws Exception {
    // 1. 加载Excel文件
    Workbook workbook = WorkbookFactory.create(new File("report.xlsx"));
    
    // 2. 配置转换参数
    PdfOptions options = PdfOptions.create();
    options.setFontProvider(new DefaultFontProvider(false, false, false));
    options.setFontEncoding("UTF-8");
    
    // 3. 执行转换
    OutputStream out = new FileOutputStream("report.pdf");
    ExcelConverter converter = new ExcelConverter(workbook, options);
    converter.convert(out);
    
    // 4. 验证结果
    assertTrue(new File("report.pdf").exists());
}

七、性能对比与建议

  • 小型文件(<5MB):直接使用基础API
  • 中型文件(5-50MB):启用流式处理模式
  • 大型文件(>50MB):考虑分布式处理方案

通过合理选择转换策略和参数配置,可以在保证质量的同时实现高效的Excel到PDF转换。建议根据实际业务需求进行充分测试,选择最适合的技术方案。