java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java提取PDF表格

Java自动化提取PDF表格的全场景实现

作者:E-iceblue

随着企业数据自动化的需求日益激增,提取 PDF 中的表格的需求也越来越受到重视,本文将基于最新的 Spire.PDF for Java,展示如何精准地将 PDF 表格转换为文本、CSV 以及 Excel 格式,实现全场景的数据自动化提取,有需要的可以了解下

随着企业数据自动化的需求日益激增,提取 PDF 中的表格的需求也越来越受到重视。尽管此前我们就发布过使用 Java 提取 PDF 中的表格,并保存为 Text 文件的教程,但显然,简单的文本提取难以满足复杂的数据分析场景。

在处理财务报表、供应链清单等结构化文档时,开发者不仅需要获取数据,更需要保留其逻辑结构。本文将基于最新的 Spire.PDF for Java,展示如何精准地将 PDF 表格转换为文本、CSV 以及 Excel 格式,实现全场景的数据自动化提取。

环境准备

在进入今天的正文前,请确保你的开发环境已就绪:

<repositories>
    <repository>
        <id>com.e-iceblue</id>
        <name>e-iceblue</name>
        <url>https://repo.e-iceblue.cn/repository/maven-public/</url>
    </repository>
</repositories>
<dependencies>
    <dependency>
        <groupId>e-iceblue</groupId>
        <artifactId>spire.pdf</artifactId>
        <version>11.12.16</version>
    </dependency>
</dependencies>

或导航到 Spire.PDF for Java 的官方网站下载安装包,解压后将 jar 文件手动导入到项目中。

基础提取:将 PDF 表格转为文本

作为入门级方案,将 PDF 中的表格提取为文本适用于对格式要求不高、仅需获取原始信息的场景。

技术逻辑:利用 PdfTableExtractor 识别表格,通过遍历单元格获取字符串。

import com.spire.pdf.*;
import com.spire.pdf.utilities.PdfTable;
import com.spire.pdf.utilities.PdfTableExtractor;

import java.io.FileWriter;
import java.io.IOException;

public class ExtractTable {
    public static void main(String[] args)throws IOException {
        // 实例化PdfDocument类的对象
        PdfDocument pdf = new PdfDocument();

        // 加载PDF文档
        pdf.loadFromFile("E:/Administrator/Python1/input/项目进度.pdf");

        // 创建StringBuilder类的实例
        StringBuilder builder = new StringBuilder();

        // 创建PdfTableExtractor类的对象
        PdfTableExtractor extractor = new PdfTableExtractor(pdf);

        // 遍历每一页
        for (int page = 0; page < pdf.getPages().getCount(); page++)
        {
            // 提取页面中的表格存入PdfTable[]数组
            PdfTable[] tableLists = extractor.extractTable(page);
            if (tableLists != null && tableLists.length > 0)
            {
                //遍历表格
                for (PdfTable table : tableLists)
                {
                    int row = table.getRowCount();//获取表格行
                    int column = table.getColumnCount();//获取表格列
                    for (int i = 0; i < row; i++)
                    {
                        for (int j = 0; j < column; j++)
                        {
                            // 获取表格中的文本内容
                            String text = table.getText(i, j);

                            // 将获取的text写入StringBuilder容器
                            builder.append(text+" ");
                        }
                        builder.append("\r\n");
                    }
                }
            }
        }

        // 保存为txt文档
        FileWriter fileWriter = new FileWriter("E:/Administrator/Python1/output/提取表格为文本.txt");
        fileWriter.write(builder.toString());
        fileWriter.flush();
        fileWriter.close();
    }
}

源文件与输出文件对比图:

方案一:最简化提取——将 PDF 表格导出为 CSV

虽然保存为文本格式能够快速获取内容,但在面对需要二次计算或数据入库的场景时,将 PDF 表格导出为 CSV 是一种更合适的选择。CSV 格式通用性很高,几乎可以被所有的主流数据库系统、数据分析工具以及编程语言无差识别,是构建自动化数据流转链路的理想中间格式。它不仅写入速度极快,且内存开销低,尤其适合后端批量处理任务。

技术逻辑:CSV(逗号分隔值)是结构化数据的标准格式。我们通过 PdfTableExtractor 获取表格数据后,通过代码控制逗号分隔符输出。

import com.spire.pdf.*;  
import com.spire.pdf.utilities.*;  
  
import java.io.*;  
  
public class ExtractTable {  
    public static void main(String[] args) throws Exception {  
        // 1. 加载 PDF 文档  
        PdfDocument pdf = new PdfDocument();  
        // 请确保路径正确  
        pdf.loadFromFile("E:/Administrator/Python1/input/项目进度.pdf");  
  
        // 用于存储提取文本的 StringBuilder        StringBuilder sb = new StringBuilder();  
  
        // 2. 遍历每一页并提取表格  
        for (int i = 0; i < pdf.getPages().getCount(); i++) {  
            PdfTableExtractor extractor = new PdfTableExtractor(pdf);  
            PdfTable[] tableLists = extractor.extractTable(i);  
  
            if (tableLists != null) {  
                for (PdfTable table : tableLists) {  
                    for (int row = 0; row < table.getRowCount(); row++) {  
                        for (int col = 0; col < table.getColumnCount(); col++) {  
                            // 使用工具方法处理 CSV 特殊字符和换行  
                            String cellText = escapeCsvField(table.getText(row, col));  
                            sb.append(cellText);  
  
                            // 列之间用逗号分隔  
                            if (col < table.getColumnCount() - 1) {  
                                sb.append(",");  
                            }  
                        }  
                        // 行之间用换行符分隔  
                        sb.append("\n");  
                    }  
                }  
            }  
        }  
  
        // 3. 写入带 BOM 的 CSV 文件  
        File outFile = new File("E:/Administrator/Python1/output/提取表格为csv.csv");  
  
        // 确保输出目录存在  
        if (!outFile.getParentFile().exists()) {  
            outFile.getParentFile().mkdirs();  
        }  
  
        try (FileOutputStream fos = new FileOutputStream(outFile)) {  
            // 【核心修复】写入 UTF-8 BOM 字节,防止 Excel 打开乱码  
            fos.write(0xEF);  
            fos.write(0xBB);  
            fos.write(0xBF);  
  
            // 使用 UTF-8 编码包装输出流  
            try (Writer writer = new OutputStreamWriter(fos, "UTF-8")) {  
                writer.write(sb.toString());  
            }  
        }  
  
        pdf.close();  
        System.out.println("PDF 表格已成功导出为 CSV 文件。");  
    }  
  
    /**  
     * 处理 CSV 字段的工具方法:  
     * 1. 去除单元格内的换行符  
     * 2. 转义双引号  
     * 3. 对包含特殊字符的字段添加双引号包裹  
     */  
    private static String escapeCsvField(String text) {  
        if (text == null) return "";  
  
        // 去掉单元格内的换行符(防止破坏 CSV 行结构)  
        text = text.replaceAll("[\\n\\r]", " ");  
  
        // 处理特殊字符  
        boolean containsSpecialChar = text.contains(",") || text.contains(";") ||  
                text.contains("\"") || text.contains("\n");  
  
        if (containsSpecialChar) {  
            // 转义双引号:将 " 替换为 ""            text = text.replace("\"", "\"\"");  
            // 整个字段用双引号包裹  
            text = "\"" + text + "\"";  
        }  
  
        return text.trim();  
    }  
}

结果文件示意图:

提示:在导出 CSV 时,建议对单元格内容使用双引号包裹,以处理数据本身含有逗号的情况。此外,确保文件使用 UTF-8 (with BOM) 编码,防止在 Excel 中直接打开时出现中文乱码。

方案二:结构化导出——将 PDF 表格直接转为 Excel

由于 CSV 只能存储纯文本,合并单元格、字体等格式在导出时会丢失。如果需要保留样式,应该选择将 PDF 中的表格提取为 Excel 文件。比如说处理财务报表、审计清单等文件,单元格样式与数据息息相关。通过导出为 Excel,你可以更好地保留原 PDF 文档中的布局,避免对数据进行二次加工。

核心步骤

import com.spire.pdf.PdfDocument;  
import com.spire.pdf.utilities.PdfTable;  
import com.spire.pdf.utilities.PdfTableExtractor;  
import com.spire.xls.ExcelVersion;  
import com.spire.xls.Workbook;  
import com.spire.xls.Worksheet;  
  
public class ExtractTable {  
  
    public static void main(String[] args) {  
  
        //加载示例PDF文档  
        PdfDocument pdf = new PdfDocument("E:/Administrator/Python1/input/项目进度.pdf");  
        //创建一个PdfTableExtractor实例  
        PdfTableExtractor extractor = new PdfTableExtractor(pdf);  
        //从第一页提取表格  
        PdfTable[] pdfTables  = extractor.extractTable(0);  
        //创建一个工作簿对象  
        Workbook wb = new Workbook();  
        //删除默认工作表  
        wb.getWorksheets().clear();  
        //如果找到任何表格  
        if (pdfTables != null && pdfTables.length > 0) {  
            //循环遍历表格  
            for (int tableNum = 0; tableNum < pdfTables.length; tableNum++) {  
                //将工作表添加到工作簿  
                String sheetName = String.format("Table - %d", tableNum + 1);  
                Worksheet sheet = wb.getWorksheets().add(sheetName);  
                //循环遍历当前表格中的行  
                for (int rowNum = 0; rowNum < pdfTables[tableNum].getRowCount(); rowNum++) {  
                    //循环遍历当前表格中的列  
                    for (int colNum = 0; colNum < pdfTables[tableNum].getColumnCount(); colNum++) {  
                        //从当前表格单元格中提取数据  
                        String text = pdfTables[tableNum].getText(rowNum, colNum);  
                        //将数据插入特定单元格  
                        sheet.get(rowNum + 1, colNum + 1).setText(text);  
                    }  
                }  
                //自动调整列宽  
                for (int sheetColNum = 0; sheetColNum < sheet.getColumns().length; sheetColNum++) {  
                    sheet.autoFitColumn(sheetColNum + 1);  
                }  
            }  
        }  
        //将工作簿保存为 Excel 文件  
        wb.saveToFile("E:/Administrator/Python1/output/提取表格为excel.xlsx", ExcelVersion.Version2016);  
    }  
}

效果展示

进阶挑战:处理复杂的跨页提取

在实际业务中,我们常遇到长篇合同或大型清单,同一个表格被拆分到两个或多个物理页面。这种情况单纯依靠循环提取会导致数据断层。那么如何识别第二页顶部的表格是第一页末尾表格的延续?如何自动合并表头?

针对此类涉及坐标逻辑判断的高阶需求,我们准备了详细的进阶教程。感兴趣的话可以查看官网教程如何在 Java 中将 PDF 转换为 CSV(轻松提取 PDF 表格)

总结与技术支持

从提取 PDF 表格为文本,到涵盖 CSV 和 Excel 的全场景导出,技术工具的演进让 PDF 数据处理变得不再繁琐。通过 Spire.PDF for Java,你可以根据业务需求灵活选择轻量级的 CSV 方案或高保真的 Excel 方案。

到此这篇关于Java自动化提取PDF表格的全场景实现的文章就介绍到这了,更多相关Java提取PDF表格内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文