如何使用 C# 讀取文件中的表格
IronOCR 讓 C# 開發人員能利用先進的機器學習模型,從 PDF 和圖片中的表格擷取資料,無論是僅含基本儲存格的簡單表格,或是採用 ReadDocumentAdvanced 方法處理的合併儲存格發票等複雜結構,皆能游刃有餘。
使用標準版 Tesseract 從表格中提取資料可能相當困難,因為文字通常位於儲存格中,且在文件中零星散佈。 然而,我們的函式庫內含一個經過訓練與微調的機器學習模型,能精準地偵測並擷取表格資料。 無論是處理財務報表、庫存清單或發票資料,IronOCR 皆提供高效解析結構化資料的工具。
針對簡單的表格,請使用標準的 OcrInput 類別進行直接的表格偵測。 針對更複雜的結構,我們獨家的 ReadDocumentAdvanced 方法能提供穩健的結果,有效解析表格並傳遞資料。 此進階方法運用機器學習技術,能解析傳統 OCR 常難以處理的表格佈局、合併儲存格及複雜格式。
快速入門:一次呼叫即可擷取複雜表格儲存格
幾分鐘內即可上手——此範例展示如何透過單次 IronOCR 呼叫並使用 ReadDocumentAdvanced,從複雜文件中取得詳細的表格儲存格資料。
其操作簡便性體現在:僅需載入 PDF 檔案,即可透過進階表格偵測功能,直接回傳一組儲存格資訊清單。
以下步驟將引導您開始使用 IronOCR 讀取表格:
簡化工作流程(5 個步驟)
- 下載 C# 函式庫以從表格中擷取資料
- 準備圖像及 PDF 文件以進行資料擷取
- 將
ReadDataTables屬性設為 true 以啟用表格偵測功能 - 針對複雜表格,請使用
ReadDocumentAdvanced方法 - 擷取這些方法偵測到的資料
如何從簡單的表格中擷取資料?
將 ReadDataTables 屬性設定為 true,即可啟用透過 Tesseract 進行表格偵測的功能。 此方法適用於具有清晰儲存格邊界且無合併儲存格的基本表格。 我製作了一個簡單的表格 PDF 來測試此功能,您可由此處下載:'simple-table.pdf'。 此方法可偵測未合併儲存格的簡單表格。 若遇較複雜的表格,請參照下方所述的方法。
標準的表格偵測方法特別適用於:
- 試算表匯出
- 具有一致行/列結構的基本資料表
- 包含表格資料的報告
- 簡易庫存清單
若需處理一般的 PDF OCR 文字擷取,此方法可與 IronOCR 更廣泛的文件處理功能無縫整合。
:path=/static-assets/ocr/content-code-examples/how-to/read-table-in-document-with-tesseract.cs
using IronOcr;
using System;
using System.Data;
// Instantiate OCR engine
var ocr = new IronTesseract();
// Enable table detection
ocr.Configuration.ReadDataTables = true;
using var input = new OcrPdfInput("simple-table.pdf");
var result = ocr.Read(input);
// Retrieve the data
var table = result.Tables[0].DataTable;
// Print out the table data
foreach (DataRow row in table.Rows)
{
foreach (var item in row.ItemArray)
{
Console.Write(item + "\t");
}
Console.WriteLine();
}
Imports Microsoft.VisualBasic
Imports IronOcr
Imports System
Imports System.Data
' Instantiate OCR engine
Private ocr = New IronTesseract()
' Enable table detection
ocr.Configuration.ReadDataTables = True
Dim input = New OcrPdfInput("simple-table.pdf")
Dim result = ocr.Read(input)
' Retrieve the data
Dim table = result.Tables(0).DataTable
' Print out the table data
For Each row As DataRow In table.Rows
For Each item In row.ItemArray
Console.Write(item & vbTab)
Next item
Console.WriteLine()
Next row
如何解讀複雜的發票表格?
在商業環境中,發票是常見的複雜表格之一。 發票是包含多行多列數據的複雜表格,通常具有合併儲存格、不規則的欄寬以及嵌套結構。 透過 IronOCR,我們採用 ReadDocumentAdvanced 方法來有效處理這些內容。 該流程包含掃描文件、識別表格結構,以及提取資料。 在此範例中,我們使用"invoiceTable.pdf"檔案來展示 IronOCR 如何從發票中擷取所有資訊。
ReadDocumentAdvanced 方法需要在安裝基礎 IronOCR 套件的同時,一併安裝 IronOcr.Extensions.AdvancedScan 套件。 此擴充功能提供經過專門訓練以處理複雜文件版面配置的高階機器學習功能。
)}]
:path=/static-assets/ocr/content-code-examples/how-to/read-table-in-document-with-ml.cs
using IronOcr;
using System.Linq;
// Instantiate OCR engine
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadPdf("invoiceTable.pdf");
// Perform OCR
var result = ocr.ReadDocumentAdvanced(input);
var cellList = result.Tables.First().CellInfos;
Imports IronOcr
Imports System.Linq
' Instantiate OCR engine
Dim ocr = New IronTesseract()
Using input As New OcrInput()
input.LoadPdf("invoiceTable.pdf")
' Perform OCR
Dim result = ocr.ReadDocumentAdvanced(input)
Dim cellList = result.Tables.First().CellInfos
End Using
此方法將文件的文字資料分為兩類:一類由邊框包圍,另一類則無邊框。 針對帶邊框的內容,該函式庫會根據表格結構進一步將其劃分為子區段。 此方法特別擅長處理:
- 描述內容各異的發票明細項目
- 多欄位價格明細
- 寄送地址與帳單地址區塊
- 稅金與總額計算區段
- 頁首與頁尾資訊
翻譯結果如下所示。 由於此方法著重於邊框包圍的資訊,任何橫跨多行的合併儲存格將被視為單一儲存格。
擷取的資料呈現為何?
如何組織與處理提取的表格儲存格?
在目前的實作中,擷取的儲存格尚未妥善整理。 然而,每個儲存格都包含寶貴的資訊,例如 X 和 Y 座標、尺寸等。 利用這些資料,我們可以建立用於各種用途的輔助類別。 儲存格資訊包含:
- 用於定位的精確 X/Y 座標
- 寬度和高度尺寸
- 文字內容
- 信心分數
- 儲存格關聯性
透過這些詳細資訊,您可透過程式化方式重建表格結構,並套用自訂邏輯進行資料擷取。 您亦可利用這些座標,在後續操作中定義特定區域以進行針對性的 OCR 處理。
以下是一些基本的輔助方法:
using System;
using System.Collections.Generic;
using System.Linq;
// A helper class to process table data by sorting cells based on coordinates
public static class TableProcessor
{
// Method to organize cells by their coordinates (Y top to bottom, X left to right)
public static List<CellInfo> OrganizeCellsByCoordinates(List<CellInfo> cells)
{
// Sort cells by Y (top to bottom), then by X (left to right)
var sortedCells = cells
.OrderBy(cell => cell.CellRect.Y)
.ThenBy(cell => cell.CellRect.X)
.ToList();
return sortedCells;
}
// Example method demonstrating how to process multiple tables
public static void ProcessTables(Tables tables)
{
foreach (var table in tables)
{
var sortedCells = OrganizeCellsByCoordinates(table.CellInfos);
Console.WriteLine("Organized Table Cells:");
// Initialize previous Y coordinate
int previousY = sortedCells.Any() ? sortedCells.First().CellRect.Y : 0;
foreach (var cell in sortedCells)
{
// Print a new line if the Y-coordinate changes, indicating a new row
if (Math.Abs(cell.CellRect.Y - previousY) > cell.CellRect.Height * 0.8)
{
Console.WriteLine(); // Start a new row
previousY = cell.CellRect.Y;
}
// Print the cell text followed by a tab
Console.Write($"{cell.CellText}\t");
}
Console.WriteLine("\n--- End of Table ---"); // End of a table
}
}
// Method to extract a specific row by the given index
public static List<CellInfo> ExtractRowByIndex(TableInfo table, int rowIndex)
{
if (table == null || table.CellInfos == null || !table.CellInfos.Any())
{
throw new ArgumentException("Table is empty or invalid.");
}
var sortedCells = OrganizeCellsByCoordinates(table.CellInfos);
List<List<CellInfo>> rows = new List<List<CellInfo>>();
// Group cells into rows based on Y coordinates
int previousY = sortedCells.First().CellRect.Y;
List<CellInfo> currentRow = new List<CellInfo>();
foreach (var cell in sortedCells)
{
if (Math.Abs(cell.CellRect.Y - previousY) > cell.CellRect.Height * 0.8)
{
// Store the completed row and start a new one
rows.Add(new List<CellInfo>(currentRow));
currentRow.Clear();
previousY = cell.CellRect.Y;
}
currentRow.Add(cell);
}
// Add the last row if it wasn't added yet
if (currentRow.Any())
{
rows.Add(currentRow);
}
// Retrieve the specified row
if (rowIndex < 0 || rowIndex >= rows.Count)
{
throw new IndexOutOfRangeException($"Row index {rowIndex} is out of range.");
}
return rows[rowIndex];
}
}
using System;
using System.Collections.Generic;
using System.Linq;
// A helper class to process table data by sorting cells based on coordinates
public static class TableProcessor
{
// Method to organize cells by their coordinates (Y top to bottom, X left to right)
public static List<CellInfo> OrganizeCellsByCoordinates(List<CellInfo> cells)
{
// Sort cells by Y (top to bottom), then by X (left to right)
var sortedCells = cells
.OrderBy(cell => cell.CellRect.Y)
.ThenBy(cell => cell.CellRect.X)
.ToList();
return sortedCells;
}
// Example method demonstrating how to process multiple tables
public static void ProcessTables(Tables tables)
{
foreach (var table in tables)
{
var sortedCells = OrganizeCellsByCoordinates(table.CellInfos);
Console.WriteLine("Organized Table Cells:");
// Initialize previous Y coordinate
int previousY = sortedCells.Any() ? sortedCells.First().CellRect.Y : 0;
foreach (var cell in sortedCells)
{
// Print a new line if the Y-coordinate changes, indicating a new row
if (Math.Abs(cell.CellRect.Y - previousY) > cell.CellRect.Height * 0.8)
{
Console.WriteLine(); // Start a new row
previousY = cell.CellRect.Y;
}
// Print the cell text followed by a tab
Console.Write($"{cell.CellText}\t");
}
Console.WriteLine("\n--- End of Table ---"); // End of a table
}
}
// Method to extract a specific row by the given index
public static List<CellInfo> ExtractRowByIndex(TableInfo table, int rowIndex)
{
if (table == null || table.CellInfos == null || !table.CellInfos.Any())
{
throw new ArgumentException("Table is empty or invalid.");
}
var sortedCells = OrganizeCellsByCoordinates(table.CellInfos);
List<List<CellInfo>> rows = new List<List<CellInfo>>();
// Group cells into rows based on Y coordinates
int previousY = sortedCells.First().CellRect.Y;
List<CellInfo> currentRow = new List<CellInfo>();
foreach (var cell in sortedCells)
{
if (Math.Abs(cell.CellRect.Y - previousY) > cell.CellRect.Height * 0.8)
{
// Store the completed row and start a new one
rows.Add(new List<CellInfo>(currentRow));
currentRow.Clear();
previousY = cell.CellRect.Y;
}
currentRow.Add(cell);
}
// Add the last row if it wasn't added yet
if (currentRow.Any())
{
rows.Add(currentRow);
}
// Retrieve the specified row
if (rowIndex < 0 || rowIndex >= rows.Count)
{
throw new IndexOutOfRangeException($"Row index {rowIndex} is out of range.");
}
return rows[rowIndex];
}
}
Imports Microsoft.VisualBasic
Imports System
Imports System.Collections.Generic
Imports System.Linq
' A helper class to process table data by sorting cells based on coordinates
Public Module TableProcessor
' Method to organize cells by their coordinates (Y top to bottom, X left to right)
Public Function OrganizeCellsByCoordinates(ByVal cells As List(Of CellInfo)) As List(Of CellInfo)
' Sort cells by Y (top to bottom), then by X (left to right)
Dim sortedCells = cells.OrderBy(Function(cell) cell.CellRect.Y).ThenBy(Function(cell) cell.CellRect.X).ToList()
Return sortedCells
End Function
' Example method demonstrating how to process multiple tables
Public Sub ProcessTables(ByVal tables As Tables)
For Each table In tables
Dim sortedCells = OrganizeCellsByCoordinates(table.CellInfos)
Console.WriteLine("Organized Table Cells:")
' Initialize previous Y coordinate
Dim previousY As Integer = If(sortedCells.Any(), sortedCells.First().CellRect.Y, 0)
For Each cell In sortedCells
' Print a new line if the Y-coordinate changes, indicating a new row
If Math.Abs(cell.CellRect.Y - previousY) > cell.CellRect.Height * 0.8 Then
Console.WriteLine() ' Start a new row
previousY = cell.CellRect.Y
End If
' Print the cell text followed by a tab
Console.Write($"{cell.CellText}" & vbTab)
Next cell
Console.WriteLine(vbLf & "--- End of Table ---") ' End of a table
Next table
End Sub
' Method to extract a specific row by the given index
Public Function ExtractRowByIndex(ByVal table As TableInfo, ByVal rowIndex As Integer) As List(Of CellInfo)
If table Is Nothing OrElse table.CellInfos Is Nothing OrElse Not table.CellInfos.Any() Then
Throw New ArgumentException("Table is empty or invalid.")
End If
Dim sortedCells = OrganizeCellsByCoordinates(table.CellInfos)
Dim rows As New List(Of List(Of CellInfo))()
' Group cells into rows based on Y coordinates
Dim previousY As Integer = sortedCells.First().CellRect.Y
Dim currentRow As New List(Of CellInfo)()
For Each cell In sortedCells
If Math.Abs(cell.CellRect.Y - previousY) > cell.CellRect.Height * 0.8 Then
' Store the completed row and start a new one
rows.Add(New List(Of CellInfo)(currentRow))
currentRow.Clear()
previousY = cell.CellRect.Y
End If
currentRow.Add(cell)
Next cell
' Add the last row if it wasn't added yet
If currentRow.Any() Then
rows.Add(currentRow)
End If
' Retrieve the specified row
If rowIndex < 0 OrElse rowIndex >= rows.Count Then
Throw New IndexOutOfRangeException($"Row index {rowIndex} is out of range.")
End If
Return rows(rowIndex)
End Function
End Module
表格擷取的最佳實務
在 IronOCR 中進行表格擷取時,請遵循以下最佳實務:
-
文件品質:解析度越高的文件,翻譯效果越佳。 針對掃描文件,請確保解析度至少為 300 DPI。
-
預處理:對於品質不佳或表格變形的文件,建議在處理前使用 IronOCR 的影像校正功能。
-
效能:對於包含多個表格的大型文件,請考慮使用多執行緒與非同步支援,以並行處理各頁面。
-
輸出選項:提取表格資料後,您可以將結果匯出為多種格式。 進一步了解資料輸出選項,以及如何將處理後的文件轉為可搜尋的 PDF 檔案。
- 流處理:對於處理記憶體內文件的網頁應用程式或情境,建議使用 PDF 流的 OCR 功能,以避免進行檔案系統操作。
摘要
IronOCR 透過基於標準 Tesseract 的偵測技術以及先進的機器學習方法,提供強大的表格擷取功能。 標準方法適用於簡單的表格,而 ReadDocumentAdvanced 方法則特別擅長處理發票等複雜文件。 透過提供的輔助方法,您可以根據具體需求來組織和處理擷取到的資料。
探索更多 IronOCR 功能,以優化您的文件處理工作流程,並在您的 .NET 應用程式中充分發揮光學字元辨識技術的潛力。
常見問題
如何使用 C# 從 PDF 和圖片中擷取表格資料?
IronOCR 讓 C# 開發人員能利用先進的機器學習模型,從 PDF 和圖片中擷取表格資料。針對簡單的表格,請使用 OcrInput 類別,並將 ReadDataTables 屬性設為 true。若遇到包含合併儲存格的複雜表格,請使用 ReadDocumentAdvanced 方法以獲得更精確的結果。
簡單與複雜的表格擷取有何區別?
IronOCR 的簡易表格擷取功能透過 Tesseract 的 ReadDataTables 屬性實現,適用於具有清晰儲存格邊界的基礎表格。若需擷取複雜表格,則需使用 ReadDocumentAdvanced 方法,該方法運用機器學習技術來處理合併儲存格、發票及複雜格式。
如何快速從複雜的表格中擷取資料?
透過單一呼叫使用 IronOCR 的 ReadDocumentAdvanced 方法:var cells = new IronTesseract().ReadDocumentAdvanced(new OcrInput().LoadPdf('invoiceTable.pdf')).Tables.First().CellInfos; 此方法運用機器學習來理解表格佈局與複雜格式。
哪些類型的文件最適合使用簡易表格偵測功能?
IronOCR 的簡易表格偵測方法特別適用於試算表匯出檔、具有一致行/列結構的基本資料表、包含表格資料的報表,以及未合併儲存格的簡易庫存清單。
如何啟用基本表格的表格偵測功能?
若要在 IronOCR 中啟用基本表格的表格偵測功能,請將 ReadDataTables 屬性設定為 true。此功能會使用 Tesseract 的表格偵測能力,對於具有清晰儲存格邊界且無合併儲存格的表格效果良好。
該函式庫能否處理版面配置複雜的發票和財務報表?
是的,IronOCR 的 ReadDocumentAdvanced 方法專為處理發票和財務報告等複雜文件而設計。它採用經過訓練的機器學習模型,能夠偵測並從具有合併儲存格和複雜格式的表格中提取資料。
IronOCR 能否整合至現有應用程式中?
IronOCR 設計上可輕鬆透過 C# 整合至現有應用程式中,讓開發人員能以最少的努力,為其軟體增添 OCR 功能。
使用 IronOCR 進行文件管理有哪些好處?
使用 IronOCR 進行文件管理,可將掃描文件轉換為可搜尋且可編輯的文字,從而簡化工作流程,減少人工資料輸入的需求,並提升文件的可存取性。
IronOCR 如何提升資料準確性?
IronOCR 透過其先進的辨識演算法與影像校正功能來提升資料準確性,確保文字擷取過程既可靠又精確。
IronOCR 是否有提供免費試用版?
是的,Iron Software 提供 IronOCR 的免費試用版,讓使用者能在決定購買前測試其功能與效能。

