在生产环境中测试,无水印。
随时随地满足您的需求。
获得30天的全功能产品。
几分钟内就能启动并运行。
在您的产品试用期间,全面访问我们的支持工程团队。
从 PDF 文档中提取结构化表格数据是 C# 开发人员的常见需求,这对于数据分析、报告或将信息集成到其他系统中至关重要。 然而,PDF 主要设计用于一致的视觉呈现,而不是直接的数据提取。 这使得以编程方式从PDF文件中读取表格在C#中成为一项具有挑战性的任务,特别是因为表格可能有很大不同——从简单的基于文本的网格到具有合并单元格的复杂布局,甚至是嵌入在扫描文档中的图像形式的表格。
本指南提供了关于如何使用IronPDF进行PDF表格提取的全面C#教程。 我们将主要探索利用IronPDF强大的文本提取功能,从基于文本的PDF中访问并解析表格数据。 我们将讨论这种方法的有效性,提供解析策略,并提供处理提取信息的见解。 此外,我们还将讨论应对更复杂情况的策略,包括扫描的PDF。
在C#中从PDF提取表格数据的关键步骤
安装用于PDF处理的IronPDF C#库(https://nuget.org/packages/IronPdf/)。
(可选演示步骤)使用 IronPDF 的 RenderHtmlAsPdf
从 HTML 字符串创建包含表格的示例 PDF。 (请参见章节:(演示步骤)使用表格数据创建 PDF 文档)
加载任何PDF文档,并使用ExtractAllText
方法检索其原始文本内容。 (请参见章节:从PDF中提取包含表格数据的所有文本)
实现 C# 逻辑以解析提取的文本并识别表格行和单元格。 (请参见章节:在C#中解析提取的文本以重建表格数据)
输出结构化的表格数据或将其保存到CSV文件中以供进一步使用。 (请参见章节:在C#中解析提取的文本以重建表格数据)
考虑使用高级技术,例如用于扫描PDF的OCR(稍后讨论)。
IronPDF 是一个C# .NET 库解决方案,用于在 .NET 中操作 PDF (https://ironpdf.com/),帮助开发人员在他们的软件应用程序中轻松读取、创建和编辑 PDF 文档。 其强大的Chromium引擎能够以高精度和速度从HTML渲染PDF文档。 它允许开发人员从不同格式无缝转换为 PDF,反之亦然。 它支持最新的 .NET 框架,包括 .NET 7、.NET 6、5、4、.NET Core 和 Standard。
此外,IronPDF .NET API 还使开发人员能够操作和编辑 PDF,添加页眉和页脚,并且更重要的是,可以轻松地从 PDF 中提取文本、图像和(正如我们将看到的)表格数据。
要从PDF文档中提取表格数据,我们将设置一个C#项目:
Visual Studio:确保您已安装 Visual Studio(例如,2022)。 如果没有,请从 Visual Studio 网站下载 (https://visualstudio.microsoft.com/downloads/)。
创建项目:
Visual Studio 的开始屏幕
在 Visual Studio 中创建一个新的控制台应用程序
配置新创建的应用程序
选择一个 .NET Framework
安装 IronPDF:
使用 Visual Studio NuGet 包管理器:
工具和管理NuGet软件包
工具和管理NuGet软件包
直接下载 NuGet 包:访问 IronPDF 的 NuGet 包页面(https://www.nuget.org/packages/IronPdf/)。
在本教程中,我们将首先创建一个包含简单表格的样例PDF,该表格来自一个HTML字符串。 这为我们提供了一个已知的PDF结构,以展示提取过程。 在实际场景中,您将加载您已有的PDF文件。
添加IronPDF命名空间,并可选择设置您的许可证密钥(IronPDF在开发过程中免费使用,但在商业部署中不带水印需要许可证):
using IronPdf;
using System; // For StringSplitOptions, Console
using System.IO; // For StreamWriter
// Apply your license key if you have one. Otherwise, IronPDF runs in trial mode.
// License.LicenseKey = "YOUR-TRIAL/PURCHASED-LICENSE-KEY";
using IronPdf;
using System; // For StringSplitOptions, Console
using System.IO; // For StreamWriter
// Apply your license key if you have one. Otherwise, IronPDF runs in trial mode.
// License.LicenseKey = "YOUR-TRIAL/PURCHASED-LICENSE-KEY";
Imports IronPdf
Imports System ' For StringSplitOptions, Console
Imports System.IO ' For StreamWriter
' Apply your license key if you have one. Otherwise, IronPDF runs in trial mode.
' License.LicenseKey = "YOUR-TRIAL/PURCHASED-LICENSE-KEY";
这是我们示例表格的HTML字符串:
string HTML = "<html>" +
"<style>" +
"table, th, td {" +
"border:1px solid black;" +
"}" +
"</style>" +
"<body>" +
"<h1>A Simple table example</h1>" + // Corrected typo: h1 not h2
"<table>" +
"<tr>" +
"<th>Company</th>" +
"<th>Contact</th>" +
"<th>Country</th>" +
"</tr>" +
"<tr>" +
"<td>Alfreds Futterkiste</td>" +
"<td>Maria Anders</td>" +
"<td>Germany</td>" +
"</tr>" +
"<tr>" +
"<td>Centro comercial Moctezuma</td>" +
"<td>Francisco Chang</td>" +
"<td>Mexico</td>" +
"</tr>" +
"</table>" +
"<p>To understand the example better, we have added borders to the table.</p>" +
"</body>" +
"</html>";
string HTML = "<html>" +
"<style>" +
"table, th, td {" +
"border:1px solid black;" +
"}" +
"</style>" +
"<body>" +
"<h1>A Simple table example</h1>" + // Corrected typo: h1 not h2
"<table>" +
"<tr>" +
"<th>Company</th>" +
"<th>Contact</th>" +
"<th>Country</th>" +
"</tr>" +
"<tr>" +
"<td>Alfreds Futterkiste</td>" +
"<td>Maria Anders</td>" +
"<td>Germany</td>" +
"</tr>" +
"<tr>" +
"<td>Centro comercial Moctezuma</td>" +
"<td>Francisco Chang</td>" +
"<td>Mexico</td>" +
"</tr>" +
"</table>" +
"<p>To understand the example better, we have added borders to the table.</p>" +
"</body>" +
"</html>";
现在,使用ChromePdfRenderer
从此 HTML 创建 PDF:
var renderer = new ChromePdfRenderer();
PdfDocument pdfDocument = renderer.RenderHtmlAsPdf(HTML);
pdfDocument.SaveAs("table_example.pdf");
Console.WriteLine("Sample PDF 'table_example.pdf' created.");
var renderer = new ChromePdfRenderer();
PdfDocument pdfDocument = renderer.RenderHtmlAsPdf(HTML);
pdfDocument.SaveAs("table_example.pdf");
Console.WriteLine("Sample PDF 'table_example.pdf' created.");
Dim renderer = New ChromePdfRenderer()
Dim pdfDocument As PdfDocument = renderer.RenderHtmlAsPdf(HTML)
pdfDocument.SaveAs("table_example.pdf")
Console.WriteLine("Sample PDF 'table_example.pdf' created.")
SaveAs
方法保存 PDF。 生成的table_example.pdf
将如下所示(基于HTML的概念图):
在NuGet包管理器UI中搜索IronPDF
要提取表格数据,首先加载 PDF(无论是我们刚创建的 PDF 还是任何现有的 PDF),然后使用 ExtractAllText
方法。 此方法从PDF页面中检索所有文本内容。
// Load the PDF (if you just created it, it's already loaded in pdfDocument)
// If loading an existing PDF:
// PdfDocument pdfDocument = PdfDocument.FromFile("table_example.pdf");
// Or use the one created above:
string allText = pdfDocument.ExtractAllText();
// Load the PDF (if you just created it, it's already loaded in pdfDocument)
// If loading an existing PDF:
// PdfDocument pdfDocument = PdfDocument.FromFile("table_example.pdf");
// Or use the one created above:
string allText = pdfDocument.ExtractAllText();
' Load the PDF (if you just created it, it's already loaded in pdfDocument)
' If loading an existing PDF:
' PdfDocument pdfDocument = PdfDocument.FromFile("table_example.pdf");
' Or use the one created above:
Dim allText As String = pdfDocument.ExtractAllText()
allText
变量现在包含PDF的所有文本内容。 您可以显示它以查看原始提取:
Console.WriteLine("\n--- Raw Extracted Text ---");
Console.WriteLine(allText);
Console.WriteLine("\n--- Raw Extracted Text ---");
Console.WriteLine(allText);
Imports Microsoft.VisualBasic
Console.WriteLine(vbLf & "--- Raw Extracted Text ---")
Console.WriteLine(allText)
要提取文本的PDF文件
在提取原始文本后,下一个挑战是解析此字符串以识别和构建表格数据。 这一步高度依赖于您PDF中表格的一致性和格式。
常规解析策略:
识别行分隔符:换行符(\n
或 \r\n
)是常见的行分隔符。
识别列分隔符: 行内的单元格可能由多个空格、制表符或特定已知字符(如“ ' 或 '; 有时候,如果列在视觉上对齐但缺乏明确的文本分隔符,您可能会基于一致的间距模式来推断结构,尽管这更为复杂。
过滤非表格内容: ExtractAllText
方法获取所有文本。 您需要通过查找标题关键词或跳过前言/后记文本的方式,使用逻辑来分离出实际构成表格的文本。
C# String.Split
方法是实现这一点的基本工具。 以下是一个示例,尝试从我们的样本中仅提取表格行,过滤掉带有句号的行(这是针对这个特定示例的简单启发式方法):
Console.WriteLine("\n--- Parsed Table Data (Simple Heuristic) ---");
string[] textLines = allText.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string line in textLines)
{
// Simple filter: skip lines with a period, assuming they are not table data in this example
// and skip lines that are too short or headers if identifiable
if (line.Contains(".")
line.Contains("A Simple table example")
line.Length < 5)
{
continue;
}
else
{
// Further split line into cells based on expected delimiters (e.g., multiple spaces)
// This part requires careful adaptation to your PDF's table structure
// Example: string[] cells = line.Split(new[] { " ", "\t" }, StringSplitOptions.None);
Console.WriteLine(line); // For now, just print the filtered line
}
}
Console.WriteLine("\n--- Parsed Table Data (Simple Heuristic) ---");
string[] textLines = allText.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string line in textLines)
{
// Simple filter: skip lines with a period, assuming they are not table data in this example
// and skip lines that are too short or headers if identifiable
if (line.Contains(".")
line.Contains("A Simple table example")
line.Length < 5)
{
continue;
}
else
{
// Further split line into cells based on expected delimiters (e.g., multiple spaces)
// This part requires careful adaptation to your PDF's table structure
// Example: string[] cells = line.Split(new[] { " ", "\t" }, StringSplitOptions.None);
Console.WriteLine(line); // For now, just print the filtered line
}
}
Imports Microsoft.VisualBasic
Console.WriteLine(vbLf & "--- Parsed Table Data (Simple Heuristic) ---")
Dim textLines() As String = allText.Split( { ControlChars.Cr, ControlChars.Lf }, StringSplitOptions.RemoveEmptyEntries)
For Each line As String In textLines
' Simple filter: skip lines with a period, assuming they are not table data in this example
' and skip lines that are too short or headers if identifiable
If line.Contains(".") line.Contains("A Simple table example") line.Length < 5 Then
Continue For
Else
' Further split line into cells based on expected delimiters (e.g., multiple spaces)
' This part requires careful adaptation to your PDF's table structure
' Example: string[] cells = line.Split(new[] { " ", "\t" }, StringSplitOptions.None);
Console.WriteLine(line) ' For now, just print the filtered line
End If
Next line
此代码将文本分成多行。 if
条件是针对这个具体示例中的非表格文本的一个非常基本的过滤器。 在实际场景中,您需要更健壮的逻辑来准确识别和解析表行和单元格。
简单过滤文本的输出:
控制台显示提取的文本
文本解析方法的重要注意事项:
限制:此方法可能在以下方面遇到困难:
具有合并单元格或复杂嵌套结构的表格。
表格中的列是通过视觉间距而不是文本分隔符来定义的。
作为图像嵌入的表格(需要 OCR)。
您可以将过滤的行(理想情况下代表表格行)保存到CSV文件中:
using (StreamWriter file = new StreamWriter("parsed_table_data.csv", false))
{
file.WriteLine("Company,Contact,Country"); // Write CSV Header
foreach (string line in textLines)
{
if (line.Contains(".")
line.Contains("A Simple table example")
line.Length < 5)
{
continue;
}
else
{
// For a real CSV, you'd split 'line' into cells and join with commas
// E.g., string[] cells = line.Split(new[] {" "}, StringSplitOptions.RemoveEmptyEntries);
// string csvLine = string.Join(",", cells);
// file.WriteLine(csvLine);
file.WriteLine(line.Replace(" ", ",").Trim()); // Basic replacement for this example
}
}
}
Console.WriteLine("\nFiltered table data saved to parsed_table_data.csv");
using (StreamWriter file = new StreamWriter("parsed_table_data.csv", false))
{
file.WriteLine("Company,Contact,Country"); // Write CSV Header
foreach (string line in textLines)
{
if (line.Contains(".")
line.Contains("A Simple table example")
line.Length < 5)
{
continue;
}
else
{
// For a real CSV, you'd split 'line' into cells and join with commas
// E.g., string[] cells = line.Split(new[] {" "}, StringSplitOptions.RemoveEmptyEntries);
// string csvLine = string.Join(",", cells);
// file.WriteLine(csvLine);
file.WriteLine(line.Replace(" ", ",").Trim()); // Basic replacement for this example
}
}
}
Console.WriteLine("\nFiltered table data saved to parsed_table_data.csv");
Imports Microsoft.VisualBasic
Using file As New StreamWriter("parsed_table_data.csv", False)
file.WriteLine("Company,Contact,Country") ' Write CSV Header
For Each line As String In textLines
If line.Contains(".") line.Contains("A Simple table example") line.Length < 5 Then
Continue For
Else
' For a real CSV, you'd split 'line' into cells and join with commas
' E.g., string[] cells = line.Split(new[] {" "}, StringSplitOptions.RemoveEmptyEntries);
' string csvLine = string.Join(",", cells);
' file.WriteLine(csvLine);
file.WriteLine(line.Replace(" ", ",").Trim()) ' Basic replacement for this example
End If
Next line
End Using
Console.WriteLine(vbLf & "Filtered table data saved to parsed_table_data.csv")
从复杂或基于图像的PDF表格中提取数据通常需要比简单文本解析更先进的技术。 IronPDF 提供的功能可以协助:
ExtractAllText()
无法将其捕获。 IronOCR 的文字检测 功能可以先将这些图像转换为文本。// Conceptual OCR usage (refer to IronOCR's documentation for detailed implementation)
// Install Package IronOcr
using IronOcr;
using (var ocrInput = new OcrInput("scanned_pdf_with_table.pdf"))
{
ocrInput.TargetDPI = 300; // Good DPI for OCR accuracy
var ocrResult = new IronOcr().Read(ocrInput);
string ocrExtractedText = ocrResult.Text;
// Now, apply parsing logic to 'ocrExtractedText'
Console.WriteLine("\n--- OCR Extracted Text for Table Parsing ---");
Console.WriteLine(ocrExtractedText);
}
// Conceptual OCR usage (refer to IronOCR's documentation for detailed implementation)
// Install Package IronOcr
using IronOcr;
using (var ocrInput = new OcrInput("scanned_pdf_with_table.pdf"))
{
ocrInput.TargetDPI = 300; // Good DPI for OCR accuracy
var ocrResult = new IronOcr().Read(ocrInput);
string ocrExtractedText = ocrResult.Text;
// Now, apply parsing logic to 'ocrExtractedText'
Console.WriteLine("\n--- OCR Extracted Text for Table Parsing ---");
Console.WriteLine(ocrExtractedText);
}
' Conceptual OCR usage (refer to IronOCR's documentation for detailed implementation)
' Install Package IronOcr
Imports Microsoft.VisualBasic
Imports IronOcr
Using ocrInput As New OcrInput("scanned_pdf_with_table.pdf")
ocrInput.TargetDPI = 300 ' Good DPI for OCR accuracy
Dim ocrResult = (New IronOcr()).Read(ocrInput)
Dim ocrExtractedText As String = ocrResult.Text
' Now, apply parsing logic to 'ocrExtractedText'
Console.WriteLine(vbLf & "--- OCR Extracted Text for Table Parsing ---")
Console.WriteLine(ocrExtractedText)
End Using
有关详细指南,请访问 IronOCR 文档(https://ironsoftware.com/csharp/ocr/)。 执行OCR后,您将解析生成的文本字符串。
ExtractAllText()
提供了文本流,但某些情况下可能会从了解每个文本片段的x,y坐标中受益。 如果IronPDF提供API来获取包含其边界框信息的文本(请检查当前文档),这可能允许进行更复杂的空间解析,以基于视觉对齐重建表格。PdfDocument pdfToConvert = PdfDocument.FromFile("your_document.pdf");
string htmlOutput = pdfToConvert.ToHtmlString();
// Then use an HTML parsing library (e.g., HtmlAgilityPack) to extract tables from htmlOutput.
PdfDocument pdfToConvert = PdfDocument.FromFile("your_document.pdf");
string htmlOutput = pdfToConvert.ToHtmlString();
// Then use an HTML parsing library (e.g., HtmlAgilityPack) to extract tables from htmlOutput.
Dim pdfToConvert As PdfDocument = PdfDocument.FromFile("your_document.pdf")
Dim htmlOutput As String = pdfToConvert.ToHtmlString()
' Then use an HTML parsing library (e.g., HtmlAgilityPack) to extract tables from htmlOutput.
模式识别和正则表达式:对于具有非常可预测模式但分隔符不一致的表,应用于提取文本的复杂正则表达式有时可以隔离表数据。
选择正确的策略取决于源PDF的复杂性和一致性。 对于许多带有基于文本表格的常见商业文档,IronPDF的ExtractAllText
结合智能C#解析逻辑可以非常有效。对于基于图像的表格,其OCR功能是必不可少的。
本文演示了如何使用IronPDF在C#中从PDF文档中提取表格数据,主要关注于利用ExtractAllText()
方法以及随后的字符串解析。 我们已经看到,这种方法虽然对基于文本的表格非常有效,但更复杂的场景,例如基于图像的表格,可以通过使用IronPDF的OCR功能来处理,或者首先将PDF转换为其他格式。
IronPDF为.NET开发人员提供了一个多功能工具包,简化了从创建和编辑到全面数据提取的许多PDF相关任务。 它提供了像DOCX等格式转换为PDF。
IronPDF是免费的开发工具,并提供免费试用许可以测试其全部商业功能。 对于生产部署,有多种许可选项可供选择。
欲了解更多详细信息和高级用例,请查看官方IronPDF文档和示例(https://ironpdf.com/)