在数据处理、自动化报表生成、业务数据整合等场景中,从 PDF 文件中提取表格是一项常见需求。PDF 作为通用文档格式,虽便于数据共享,但因底层以 “视觉布局” 而非 “结构化数据” 存储,导致编程提取表格时面临格式解析、数据对齐等难题。本文将介绍如何使用 Spire.PDF for .NET 库通过 C# 提取 PDF 中的表格,并将结果导出为 TXT 和 CSV 格式以便进一步分析。
目录:
搭建 C# 开发环境
Spire.PDF for .NET 是一个功能强大的库,用于在 C# 和 VB.NET 中处理 PDF 文件。它支持广泛的 PDF 操作,包括表格提取、文本提取、图像提取等。
推荐通过 NuGet 包管理器安装 Spire.PDF(最便捷,自动处理依赖)。步骤如下:
1. 打开 Visual Studio 并创建一个新的 C# 项目。(此处新建了一个控制台应用程序);
2. 在 Visual Studio 中,右键点击项目名称 → 选择 “管理 NuGet 程序包”;
3. 在 “浏览” 页搜索 Spire.PDF,选择最新稳定版 → 点击 “安装”。
了解 PDF 表格结构
在编写代码之前,让我们先弄清楚 PDF 是如何存储表格的。与 Excel(明确定义行 / 列)不同,PDF 无原生 “表格” 概念,仅通过 3 类视觉元素模拟表格:
- 文本块:每个单元格的文本是独立元素,通过坐标(X/Y 轴)定位;
- 边框线条:水平 / 垂直线条作为视觉分隔,标识表格的行 / 列边界;
- 间距规则:文本块之间的固定间隙,辅助区分不同单元格。
Spire.PDF 的 PdfTableExtractor 类正是通过分析这些视觉元素,逆向推断出表格结构,从而实现结构化提取。
如何通过 C# 从 PDF 中提取表格
如果你需要快速预览表格数据(例如,开发调试或验证提取结果),可以直接通过控制台实时输出结果,无需生成额外文件,节省开发时间。
从 PDF 表格中提取数据的关键方法:
- PdfDocument:表示一个 PDF 文件。
- LoadFromFile:加载要处理的 PDF 文件。
- PdfTableExtractor:基于视觉线索检测 PDF 中的表格。
- ExtractTable(pageIndex):提取指定页码的所有表格,返回 PdfTable 数组。
- GetRowCount()/GetColumnCount():检索每个表格的行数和列数。
- GetText(rowIndex, columnIndex):从指定单元格中提取文本。
using Spire.Pdf;
using Spire.Pdf.Utilities;
namespace ExtractPdfTable
{
class Program
{
static void Main(string[] args)
{
// 创建PdfDocument对象
PdfDocument pdf = new PdfDocument();
// 加载PDF文件
pdf.LoadFromFile("表格.pdf");
// 初始化PdfTableExtractor类的实例
PdfTableExtractor extractor = new PdfTableExtractor(pdf);
// 循环遍历页面
for (int pageIndex = 0; pageIndex < pdf.Pages.Count; pageIndex++)
{
// 从特定页面提取表格
PdfTable[] tableList = extractor.ExtractTable(pageIndex);
// 判断表格列表是否为空
if (tableList != null && tableList.Length > 0)
{
int tableNumber = 1;
// 循环遍历列表中的表格
foreach (PdfTable table in tableList)
{
Console.WriteLine($"\n第 {pageIndex + 1} 页的第 {tableNumber} 个表格:");
Console.WriteLine("-----------------------------------");
// 获取特定表格的行数和列数
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);
// 将单元格文本打印到控制台并带有分隔符
Console.Write($"{text}\t");
}
// 每行后换行
Console.WriteLine();
}
tableNumber++;
}
}
}
// 关闭文档
pdf.Close();
}
}
}
适用场景
- 快速调试或验证提取的数据。
- 小型数据集预览。
输出: 检索 PDF 表格数据并输出到控制台
C# 提取 PDF 表格到 TXT 文本文件
对于轻量级的数据存档,将表格保存到文本文件是理想的选择。此方法使用 StringBuilder 高效地编译表格数据,保留换行符以提高可读性。
将 PDF 表格导出到 TXT 的主要优势:
- 高效性:StringBuilder 优化文本拼接效率,减少内存占用。
- 可读性:保留表格的行结构,用换行符\r\n分隔行,避免数据杂乱。
- 兼容性:TXT 格式无平台限制,Windows、macOS、Linux 均可直接打开,无需依赖专用软件。
using Spire.Pdf;
using Spire.Pdf.Utilities;
using System.Text;
namespace ExtractTableToTxt
{
class Program
{
static void Main(string[] args)
{
// 创建PdfDocument对象
PdfDocument pdf = new PdfDocument();
// 加载PDF文件
pdf.LoadFromFile("表格.pdf");
// 创建StringBuilder对象
StringBuilder builder = new StringBuilder();
// 初始化PdfTableExtractor类的实例
PdfTableExtractor extractor = new PdfTableExtractor(pdf);
// 声明PdfTable数组
PdfTable[] tableList = null;
// 循环遍历页面
for (int pageIndex = 0; pageIndex < pdf.Pages.Count; pageIndex++)
{
// 从特定页面提取表格
tableList = extractor.ExtractTable(pageIndex);
// 判断表格列表是否为空
if (tableList != null && tableList.Length > 0)
{
// 循环遍历列表中的表格
foreach (PdfTable table in tableList)
{
// 获取特定表格的行数和列数
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);
// 将文本添加到字符串生成器
builder.Append(text + " ");
}
builder.Append("\r\n");
}
}
}
}
// 写入.txt文件
File.WriteAllText("提取PDF表格.txt", builder.ToString());
}
}
}
适用场景
- 以轻量级、普遍可访问的格式存档表格数据。
- 跨平台共享(所有设备均可打开 TXT)。
- 简单脚本输入(如 PowerShell 后续处理)。
输出: 提取 PDF 表格数据并保存到文本文件。
扩展应用:对于VB.NET代码示例,请使用我们的 C#⇆VB.NET 转换器直接转换上述代码。
C# 将 PDF 表格导出为 CSV
CSV(逗号分隔值)是表格数据的行业标准,与 Excel、Google Sheets 和数据库兼容。此方法通过引用单元格和处理特殊字符,将提取的表格格式化为有效的 CSV 文件。
提取 PDF 表格到 CSV 的主要特点:
- StreamWriter:增量写入数据到 CSV 文件,减少大型 PDF 文件的内存占用。
- 特殊字符处理:按 CSV 标准转义单元格中的逗号和双引号,避免列错位。
- 工具兼容:生成的 CSV 可直接用 Excel 打开,无需手动调整格式,减少后续操作成本。
- 编码兼容:UTF-8 编码确保中文、特殊符号在 Excel 中正常显示(避免打开时乱码)。
using Spire.Pdf;
using Spire.Pdf.Utilities;
using System.Text;
namespace ExtractTableToCsv
{
class Program
{
static void Main(string[] args)
{
// 创建PdfDocument对象
PdfDocument pdf = new PdfDocument();
// 加载PDF文件
pdf.LoadFromFile("表格.pdf");
// 创建StreamWriter对象以高效写入CSV
using (StreamWriter csvWriter = new StreamWriter("PDF表格.csv", false, Encoding.UTF8))
{
// 创建PdfTableExtractor对象
PdfTableExtractor extractor = new PdfTableExtractor(pdf);
// 循环遍历页面
for (int pageIndex = 0; pageIndex < pdf.Pages.Count; pageIndex++)
{
// 从特定页面提取表格
PdfTable[] tableList = extractor.ExtractTable(pageIndex);
// 判断表格列表是否为空
if (tableList != null && tableList.Length > 0)
{
// 循环遍历列表中的表格
foreach (PdfTable table in tableList)
{
// 获取特定表格的行数和列数
int row = table.GetRowCount();
int column = table.GetColumnCount();
// 循环遍历行
for (int i = 0; i < row; i++)
{
// 创建列表存储数据
List<string> rowData = new List<string>();
// 循环遍历列
for (int j = 0; j < column; j++)
{
// 从表格单元格检索文本
string cellText = table.GetText(i, j).Replace("\"", "\"\"");
// 将单元格文本添加到列表并用双引号括起来
rowData.Add($"\"{cellText}\"");
}
// 用逗号连接单元格并写入CSV
csvWriter.WriteLine(string.Join(",", rowData));
}
}
}
}
}
}
}
}
适用场景
- 数据分析(导入 Excel 进行计算)。
- 将 PDF 表格迁移到数据库(导入 MySQL、SQL Server)。
输出: 解析 PDF 表格数据并导出到 CSV 文件。
推荐:与 Spire.XLS for .NET 集成,直接提取 PDF 表格到 Excel 文档。
结论
本文提供了三种在 C# 中提取 PDF 表格的有效方法。通过利用 Spire.PDF for .NET 库,开发者可以快速实现 PDF 表格的结构化提取,同时兼顾效率与兼容性。根据实际需求选择合适的导出格式,能大幅提升数据处理效率,减少人工录入成本。
如需进一步探索 PDF 处理功能(如 PDF 生成、水印添加、页面合并),可参考 Spire.PDF 官方文档;若需商业场景测试,可获取 30 天免费试用许可证。
常见问题
问题 1:为什么使用 Spire.PDF for .NET 提取表格?
答: Spire.PDF 提供了专用的 PdfTableExtractor 类,该类基于视觉提示(边框、间距和文本对齐)检测表格,简化了从 PDF 解析结构化数据的过程。
问题 2:Spire.PDF 能否从扫描 PDF 中提取表格?
答: 不能。此.NET PDF 库仅支持文本型 PDF(文本可选中、复制)。对于扫描的 PDF,请使用 Spire.OCR (OCR 文字识别库)先提取文本,然后再解析表格。
问题 3:能否一次性从多个 PDF 中提取表格?
答:可通过 Directory.GetFiles() 遍历文件夹中的所有 PDF,循环执行提取逻辑,示例代码如下:
string[] pdfFiles = Directory.GetFiles(@"C:\Invoices\", "*.pdf");
foreach (string file in pdfFiles)
{
// 表格提取的代码
}
问题 4:从大型 PDF 中提取表格时,如何提高性能?
答: 对于大型 PDF(100 + 页),通过以下方式优化性能:
- 分批处理页面,避免一次性加载整个 PDF。
- 用 using 包裹 PdfDocument 和 PdfTableExtractor,确保处理完一批页面后立即释放内存。
- 跳过没有表格的页面(
using if (tableList == null || tableList.Length == 0)
)。