提取PDF数据:Documents for PDF ( GcPdf )

news/2024/5/20 12:21:45 标签: GcPdf

在当今数据驱动的世界中,从 PDF 文档中无缝提取结构化表格数据已成为开发人员的一项关键任务。借助GrapeCity Documents for PDF ( GcPdf ),您可以使用 C# 以编程方式轻松解锁这些 PDF 中隐藏的信息宝藏。

考虑一下 PDF(最常用的文档格式之一)的流行程度,以及它的表格中可以包含的大量数据。公司和组织一直在使用 PDF 文档来查看财务分析、股票趋势、联系方式等。现在,想象一下多年来检查季度报告的情况,其中数据的积累占据了中心位置。

从这些报告中获取数据最初看起来可能很容易(复制/粘贴)。尽管如此,由于 PDF 文件的结构,简单的复制和粘贴无需大量操作和修改即可获得表格数据的情况很少见。 

再加上从许多其他文档复制和粘贴的可能性,这是一个漫长的一天(甚至一周或更长时间,取决于所需数据!)的秘诀。有效地处理此类需求需要一个能够自动执行此过程的工具,而 C# .NET GcPdf API 库是完成这项工作的完美工具!

本文适用于希望减少收集数据所需时间并提高数据收集过程准确性的开发人员。这些示例将帮助开发人员了解 GcPdf 工具,以便访问 PDF 文件中的表格并提取表格数据以便根据需要导出为 CSV 文件或其他格式(例如 XLSX)。

有关 PDF 文档中表格的重要信息

表格与 PDF 文件格式非常相似,是一种几乎流行的数据呈现方式。尽管如此,有必要了解 PDF 文档本质上缺乏表格的概念。换句话说,您在 PDF 中看到的表格纯粹是视觉元素。

这些 PDF“表格”与我们在 MS Excel 或 MS Word 等应用程序中常见的表格不同。相反,它们是通过负责在特定位置渲染文本和图形的运算符组合来构造的,类似于表格结构。

这意味着行、列和单元格的传统概念对于 PDF 文件来说是陌生的,没有底层代码组件来帮助识别这些元素。那么,让我们深入研究一下 GcPdf 的 C# API 库如何帮助我们实现这一任务!

如何使用 C# 以编程方式从 PDF 文档中提取表格数据

  1. 创建包含 GcPdf 的 .NET Core 控制台应用程序
  2. 加载包含数据表的示例 PDF
  3. 定义表识别参数
  4. 获取表数据
  5. 将提取的 PDF 表数据保存到另一种文件类型 (CSV)
  6. 奖励:将导出的 PDF 表格数据格式化为 Excel (XLSX) 文件

请务必下载示例应用程序 并尝试本博客文章中描述的用例场景和代码片段的详细实现。

创建包含 GcPdf 的 .NET Core 控制台应用程序

创建 .NET Core 控制台应用程序,右键单击“依赖项”,然后选择“管理 NuGet 包”。在“浏览”选项卡下,搜索“GrapeCity.Documents.Pdf”并单击“安装”。

PDF NuGet

安装时,您将收到“许可证接受”对话框。单击“我接受”继续。

在程序文件中,导入以下命名空间:

using System.Text;
using GrapeCity.Documents.Pdf;
using GrapeCity.Documents.Pdf.Recognition;
using System.Linq;

加载包含数据表的示例 PDF

通过初始化GcPdfDocument 构造函数来加载将要解析的 PDF 文档来创建新的 PDF 文档。调用 GcPdfDocument 的 Load 方法来加载包含数据表的原始 PDF 文档。

using (var fs = File.OpenRead(Path.Combine("Resources", "PDFs", "zugferd-invoice.pdf")))
{
    // Initialize GcPdf
    var pdfDoc= new GcPdfDocument();
    // Load a PDF document
    pdfDoc.Load(fs);
}

在此示例中,我们将使用此 PDF:

定义表识别参数

实例化RectangleF 类的新实例并定义 PDF 文档中的表格边界。

const float DPI = 72;
using (var fs = File.OpenRead(Path.Combine("Resources", "PDFs", "zugferd-invoice.pdf")))
{
    // Initialize GcPdf
    var pdfDoc= new GcPdfDocument();
    // Load a PDF document
    pdfDoc.Load(fs);
    
    // The approx table bounds:
    var tableBounds = new RectangleF(0, 2.5f * DPI, 8.5f * DPI, 3.75f * DPI);
}

为了帮助在定义的参数内识别表格,我们使用TableExtractOptions类,允许我们微调表格识别,考虑表格格式的特性。TableExtractOptions 是一个参数,用于指定表格式选项,例如列宽、行高以及行或列之间的距离。

// TableExtractOptions allow to fine-tune table recognition accounting for
// specifics of the table formatting:
var tableExtrctOpt = new TableExtractOptions();
var GetMinimumDistanceBetweenRows = tableExtrctOpt.GetMinimumDistanceBetweenRows;

// In this particular case, we slightly increase the minimum distance between rows
// to make sure cells with wrapped text are not mistaken for two cells:
tableExtrctOpt.GetMinimumDistanceBetweenRows = (list) =>
{
    var res = GetMinimumDistanceBetweenRows(list);
    return res * 1.2f;
};

获取 PDF 的表格数据

创建一个列表来保存 PDF 页面中的表格数据。

// CSV: list to keep table data from all pages:
var data = new List<List<string>>();

使用 定义的表边界(在上一步中定义)调用GetTable 方法,以使 GcPdf 搜索指定矩形内的表。

for (int i = 0; i < pdfDoc.Pages.Count; ++i)
{
  // Get the table at the specified bounds:
  var itable = pdfDoc.Pages[i].GetTable(tableBounds, tableExtrctOpt);
}

使用ITable.GetCell(rowIndex, colIndex) 方法访问表中的每个单元格。使用 Rows.Count 和 Cols.Count 属性循环访问提取的表格单元格。

for (int i = 0; i < pdfDoc.Pages.Count; ++i)
{
  // Get the table at the specified bounds:
  var itable = pdfDoc.Pages[i].GetTable(tableBounds, tableExtrctOpt);
  if (itable != null)
  {
    for (int row = 0; row < itable.Rows.Count; ++row)
    {
      // CSV: add next data row ignoring headers:
      if (row > 0)
        data.Add(new List<string>());

      for (int col = 0; col < itable.Cols.Count; ++col)
      {
        var cell = itable.GetCell(row, col);
        if (cell == null && row > 0)
          data.Last().Add("");
        else
        {
          if (cell != null && row > 0)
            data.Last().Add($"\"{cell.Text}\"");
       }
      }
    }
  }
}

将提取的 PDF 表数据保存到另一种文件类型 (CSV)

对于此步骤,我们必须首先添加对“System.Text.Encoding.CodePages”NuGet 包引用的引用。

然后,为了保存上一步中从变量中提取的 PDF 表数据,我们将使用 File 类 并调用其 AppendAllLines 方法。

for (int i = 0; i < pdfDoc.Pages.Count; ++i)
{
   // Get the table at the specified bounds:
    var itable = pdfDoc.Pages[i].GetTable(tableBounds, tableExtrctOpt);
    if (itable != null)
    {
      for (int row = 0; row < itable.Rows.Count; ++row)
      {
       // CSV: add next data row ignoring headers:
        if (row > 0)
           data.Add(new List<string>());
        for (int col = 0; col < itable.Cols.Count; ++col)
        {
          var cell = itable.GetCell(row, col);
          if (cell == null && row > 0)
            data.Last().Add("");
          else
          {
           if (cell != null && row > 0)
            data.Last().Add($"\"{cell.Text}\"");
          }
        } 
     }
  }
}

数据现在将以 CSV 文件形式提供:

原版PDF

在 CSV 文件中提取 PDF 表数据

奖励:将导出的 PDF 表格数据格式化为 Excel (XLSX) 文件

尽管数据现在以易于读取和操作的格式提供,但它是以 CSV 文件格式的原始格式保存的。为了更好地利用数据并使分析更容易进行,请使用 GrapeCity Documents for Excel (GcExcel) .NET 版本和 C# 将 CSV 文件加载到 Excel (XLSX) 文件中,并对提取的数据应用样式和格式。 

要使用 GcExcel,请将NuGet 包“GrapeCity.Documents.Excel”添加到项目中并添加其命名空间。

using GrapeCity.Documents.Excel;

初始化 GcExcel 工作簿实例并使用Open方法加载 CSV 文件。

 var workbook = new GrapeCity.Documents.Excel.Workbook();
 workbook.Open($@"{fileName}", OpenFileFormat.Csv);

获取提取数据的范围并包装单元格范围,对列应用自动调整大小,并应用带条件背景颜色的样式。

IWorksheet worksheet = workbook.Worksheets[0];
IRange range = worksheet.Range["A2:E10"];

// wrapping cell content
range.WrapText = true;

// styling column names 
worksheet.Range["A1"].EntireRow.Font.Bold = true;

// auto-sizing range
worksheet.Range["A1:E10"].AutoFit();

// aligning cell content
worksheet.Range["A1:E10"].HorizontalAlignment = HorizontalAlignment.Center;
worksheet.Range["A1:E10"].VerticalAlignment = VerticalAlignment.Center;

// applying conditional format on UnitPrice
IColorScale twoColorScaleRule = worksheet.Range["E2:E10"].FormatConditions.AddColorScale(ColorScaleType.TwoColorScale);

twoColorScaleRule.ColorScaleCriteria[0].Type = ConditionValueTypes.LowestValue;
twoColorScaleRule.ColorScaleCriteria[0].FormatColor.Color = Color.FromArgb(255, 229, 229);

twoColorScaleRule.ColorScaleCriteria[1].Type = ConditionValueTypes.HighestValue;
twoColorScaleRule.ColorScaleCriteria[1].FormatColor.Color = Color.FromArgb(255, 20, 20);

Thread.Sleep(1000);                

最后,使用Save方法将工作簿保存为 Excel 文件:

workbook.Save("ExtractedData_Formatted.xlsx");

如您所见,使用 C# 和 GcPdf,开发人员可以以编程方式将 PDF 表格数据提取到另一个文件(如 CSV),然后使用 GcExcel,可以将数据转换为风格化和格式化的 Excel XLSX 文件,以便于数据分析:

原版PDF

在 CSV 文件中提取 PDF 表数据

格式化 Excel XLSX 文件

GrapeCity 的 .NET PDF API 库

将此 .NET PDF 服务器端 API 集成到桌面或基于 Web 的应用程序中,使开发人员能够完全控制 PDF - 快速生成文档、提高内存效率且无依赖性。


http://www.niftyadmin.cn/n/5052454.html

相关文章

Field-Based DI in Spring

Field-Based DI For Field-Based DI, we can inject the dependencies by marking them with an Autowired annotation。 If there’s no constructor or setter method to inject the dependencies, the container will use reflection to inject dependencies. # Field-Bas…

算法系列-链表操作总结

我们做了单链表反转、求链表中间节点、删除链表第n个节点、链表中环的检测、判断回文链表5个练习&#xff0c;并且这5个练习都是针对单链表的&#xff1b; 在操作链表的过程中有哪些需要注意的地方呢&#xff1f; 我们可以声明一个哑结点&#xff0c;可以避免多余的判断&…

基于微信小程序的民宿短租酒店预订系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言系统主要功能&#xff1a;具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计…

聚焦云原生安全|如何为5G边缘云和工业互联网应用筑牢安全防线

9月22日&#xff0c;2023年中国信息通信业发展高层论坛5G工业互联网分论坛在北京顺利举办。 作为国内云原生安全领导厂商&#xff0c;安全狗受邀出席此次活动。 据悉&#xff0c;中国信息通信业发展高层论坛是致力于研究信息通信业发展新问题、新趋势&#xff0c;推动信息通信…

.net core DI注入,构造函数含有动态参数

使用.net core 开发的时候我们使用依赖注入来实例化需要的服务等&#xff0c;有时候这个服务类的构造函数是有参数的&#xff0c;此时想使用依赖注入就变得很麻烦。我们可以采用工厂模式&#xff0c;去构造demo如下 person类 namespace DIDynamicConstructorParams.TestDI {p…

防御XSS攻击的方法

以下是对于上述防御XSS攻击方法的具体实现示例&#xff1a; HttpOnly属性的设置&#xff1a; 在后端设置HttpOnly属性时&#xff0c;可以使用如下代码&#xff08;假设使用Node.js和Express框架&#xff09;&#xff1a; const express require(express); const app express…

距离矢量路由协议RIP(含Cisco模拟器实验命令配置)

距离矢量路由协议RIP(含Cisco模拟器实验命令配置) 简介 距离矢量路由协议&#xff08;Routing Information Protocol, RIP&#xff09;是一种内部网关协议&#xff0c;它位于应用层&#xff0c;使用520 UDP端口。RIP基于距离矢量算法&#xff08;Bellham-Ford&#xff09;根据…

进程管理--上下文切换

上下文&#xff1a;描述了任务的执行状态。包括任务执行过程中堆栈中的内容和寄存器值&#xff0c;获取的资源信息&#xff0c;自身状态等 上下文切换&#xff1a;当一个任务切换到另一个任务时&#xff0c;它需要保存当前任务的所有状态&#xff0c;即保存当前任务的上下文&a…