使用 Java 提取 PDF 表格中的数据

从 PDF 中提取表格

使用 TableAbsorber 在每页上查找表格并遍历行、单元格、文本片段和文本段。

  1. 使用 Document 实例打开源 PDF。
  2. 遍历文档 Page 对象,因为表格是逐页检测的。
  3. 创建一个 TableAbsorber 对每页进行调用 visit(page) 填充检测到的表格列表。
  4. 遍历检测到的 AbsorbedTable, AbsorbedRow, AbsorbedCell, TextFragment,以及 TextSegment 对象。
  5. 从片段内容构建提取的行文本并打印表格数据。
public static void extractTablesFromPdf(Path inputFile) {
    try (Document document = new Document(inputFile.toString())) {
        for (Page page : document.getPages()) {
            TableAbsorber absorber = new TableAbsorber();
            absorber.visit(page);

            for (AbsorbedTable table : absorber.getTableList()) {
                System.out.println("Table");
                for (AbsorbedRow row : table.getRowList()) {
                    StringBuilder rowText = new StringBuilder();
                    for (AbsorbedCell cell : row.getCellList()) {
                        if (rowText.length() > 0) {
                            rowText.append("|");
                        }
                        StringBuilder cellText = new StringBuilder();
                        for (TextFragment fragment : cell.getTextFragments()) {
                            StringBuilder fragmentText = new StringBuilder();
                            for (TextSegment segment : fragment.getSegments()) {
                                fragmentText.append(segment.getText());
                            }
                            if (cellText.length() > 0) {
                                cellText.append("|");
                            }
                            cellText.append(fragmentText);
                        }
                        rowText.append(cellText);
                    }
                    System.out.println(rowText);
                }
            }
        }
    }
}

从特定标记区域提取表格

此示例查找方形注释,将其矩形与每个检测到的表格进行比较,并仅输出位于标记区域内的表格。

  1. 使用 Document 实例打开源 PDF。
  2. 获取目标 Page 并定位方框 Annotation 标记提取区域的。
  3. 创建一个 TableAbsorber 并调用 visit(page) 检测该页上的表格。
  4. 比较每个检测到的 AbsorbedTable Rectangle 与注释矩形的边界。
  5. 遍历匹配的 AbsorbedRow 和 AbsorbedCell 对象并重建行文本。
  6. 仅打印标记区域的表格数据。
public static void extractTableFromSpecificArea(Path inputFile) {
    try (Document document = new Document(inputFile.toString())) {
        Page page = document.getPages().get_Item(1);

        Annotation squareAnnotation = null;
        for (Annotation annotation : page.getAnnotations()) {
            if (annotation.getAnnotationType() == AnnotationType.Square) {
                squareAnnotation = annotation;
                break;
            }
        }

        if (squareAnnotation == null) {
            System.out.println("No square annotation found.");
            return;
        }

        TableAbsorber absorber = new TableAbsorber();
        absorber.visit(page);

        for (AbsorbedTable table : absorber.getTableList()) {
            Rectangle tableRect = table.getRectangle();
            Rectangle annotationRect = squareAnnotation.getRect();

            boolean isInRegion = annotationRect.getLLX() < tableRect.getLLX()
                    && annotationRect.getLLY() < tableRect.getLLY()
                    && annotationRect.getURX() > tableRect.getURX()
                    && annotationRect.getURY() > tableRect.getURY();

            if (isInRegion) {
                for (AbsorbedRow row : table.getRowList()) {
                    StringBuilder rowText = new StringBuilder();
                    for (AbsorbedCell cell : row.getCellList()) {
                        if (rowText.length() > 0) {
                            rowText.append("|");
                        }
                        StringBuilder cellText = new StringBuilder();
                        for (TextFragment fragment : cell.getTextFragments()) {
                            StringBuilder fragmentText = new StringBuilder();
                            for (TextSegment segment : fragment.getSegments()) {
                                fragmentText.append(segment.getText());
                            }
                            if (cellText.length() > 0) {
                                cellText.append("|");
                            }
                            cellText.append(fragmentText);
                        }
                        rowText.append(cellText);
                    }
                    System.out.println(rowText);
                }
            }
        }
    }
}

将表导出到 Excel

  1. 使用 Document 实例打开源 PDF。
  2. 创建 ExcelSaveOptions 用于导出。
  3. 将 Excel 输出格式设置为 XLSX 因此检测到的表布局被写入为 Excel 工作簿。
  4. 呼叫 document.save(outputFile.toString(), excelSave) 将文档导出为 Excel 格式。
public static void exportTablesToExcel(Path inputFile, Path outputFile) {
    try (Document document = new Document(inputFile.toString())) {
        ExcelSaveOptions excelSave = new ExcelSaveOptions();
        excelSave.setFormat(ExcelSaveOptions.ExcelFormat.XLSX);
        document.save(outputFile.toString(), excelSave);
    }
}