IronOCR 操作指南 在文件中讀取表格 如何使用 C# 讀取文件中的表格 Curtis Chau 更新:2026年1月10日 下載 IronOCR NuGet 下載 DLL 下載 Windows 安裝程式 開始免費試用 法學碩士副本 法學碩士副本 將頁面複製為 Markdown 格式,用於 LLMs 在 ChatGPT 中打開 請向 ChatGPT 諮詢此頁面 在雙子座打開 請向 Gemini 詢問此頁面 在 Grok 中打開 向 Grok 詢問此頁面 打開困惑 向 Perplexity 詢問有關此頁面的信息 分享 在 Facebook 上分享 分享到 X(Twitter) 在 LinkedIn 上分享 複製連結 電子郵件文章 This article was translated from English: Does it need improvement? Translated View the article in English IronOCR 使 C# 開發人員能夠使用先進的機器學習模型從 PDF 和圖像中的表格中提取資料,使用 ReadDocumentAdvanced 方法既可處理具有基本單元格的簡單表格,也可處理複雜結構(如具有合併單元格的發票)。 <! -- --> <!--說明:說明程式碼概念的圖表或截圖 --> 使用純 Tesseract 從表格中萃取資料是一項挑戰,因為文字通常位於單元格中,並且稀疏地散佈在文件中。 然而,我們的資料庫包含一個經過訓練和微調的機器學習模型,可準確檢測和擷取表單資料。 無論是處理財務報告、庫存清單或發票資料,IronOCR 都能提供有效解析結構化資料的工具。 對於簡單的表格,請依賴使用標準 OcrInput class 的直接表格偵測。 對於更複雜的結構,我們獨家的 ReadDocumentAdvanced 方法可提供強大的結果,有效地解析表格並傳送資料。 這種先進的方法利用機器學習來理解表格佈局、合併的單元格以及複雜的格式,而傳統的 OCR 通常會在這些方面遇到困難。 快速入門:一次呼叫提取複雜表格單元格 在幾分鐘內就可以開始運行 - 這個範例展示了如何使用 ReadDocumentAdvanced 的單次 IronOCR 呼叫,從複雜的文件中取得詳細的表格儲存格資料。 它透過載入 PDF、應用進階表格檢測並直接返回儲存格資訊清單來展示易用性。 立即開始使用 NuGet 建立 PDF 檔案: 使用 NuGet 套件管理器安裝 IronOCR PM > Install-Package IronOcr 複製並運行這段程式碼。 var cells = new IronTesseract().ReadDocumentAdvanced(new OcrInput().LoadPdf("invoiceTable.pdf")).Tables.First().CellInfos; 部署到您的生產環境進行測試 立即開始在您的專案中使用 IronOCR,免費試用! 免費試用30天 以下步驟引導您開始使用 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 $vbLabelText $csharpLabel 如何閱讀複雜的發票表格? <! -- --> --> <!--說明:顯示程式碼執行輸出或結果的截圖 --> 在商業環境中,發票是比較常見的複雜表格之一。 發票是複雜的表格,包含多行多列的資料,通常具有合併的單元格、不同的列寬和巢狀結構。 透過 IronOCR,我們利用 ReadDocumentAdvanced 方法來有效處理它們。 該過程包括掃描文件、識別表格結構和提取資料。 在本範例中,我們使用"invoiceTable.pdf"檔案來展示 IronOCR 如何擷取發票中的所有資訊。 ReadDocumentAdvanced 方法需要 IronOcr.Extensions.AdvancedScan 套件與基本 IronOCR 套件一起安裝。 此延伸功能提供先進的機器學習能力,專門針對複雜的文件佈局進行訓練。 請注意@ 在 .NET Framework 上使用進階掃描功能需要專案在 x64 架構上運作。 進入專案配置,取消選取"首選 32 位元"選項即可實現此目的。 在以下故障排除指南中瞭解更多資訊:"Advanced Scan on .NET Framework"。 :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 $vbLabelText $csharpLabel 此方法將文件中的文字資料分為兩類:一類有邊框,另一類沒有邊框。 對於有邊框的內容,圖書館會根據表格的結構進一步細分為小節。 該方法擅長處理: 具有不同描述的發票細列項目 多欄式價格明細 送貨與帳單地址區塊 稅金和總計計算部分 頁首和頁尾資訊 結果如下圖所示。 由於此方法著重於邊界所圍繞的資訊,任何跨越多行的合併單元格將被視為單一單元格。 擷取的資料是什麼樣子? 如何組織和處理萃取的表格儲存格? 在目前實作中,提取的單元格尚未正確組織。 但是,每個單元格都包含有價值的信息,例如 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 $vbLabelText $csharpLabel 表抽取的最佳實務 在 IronOCR 中進行表格抽取工作時,請考慮這些最佳實務: 1.文件品質:較高解析度的文件能產生較好的結果。 對於掃描的文件,請確保至少 300 DPI。 2.預處理:對於品質不佳或表格歪斜的文件,可考慮在處理前使用 IronOCR 的影像修正功能。 3.效能:對於具有多個表格的大型文件,請考慮使用 多執行緒和 async 支援 來平行處理頁面。 4.輸出選項:抽取表格資料後,您可以各種格式匯出結果。 進一步瞭解 資料輸出選項,以及如何從處理過的文件建立 可搜尋的 PDF。 5.串流處理:對於網頁應用程式或處理記憶體內文件的情境,請考慮使用 OCR for PDF streams 以避免檔案系統作業。 摘要 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 IronOcrInput().LoadPdf('invoiceTable.pdf')).Tables.First().CellInfos; 這可利用機器學習來理解表格佈局和複雜格式。 哪些類型的文件最適合使用簡單的表格檢測? IronOCR 簡單的表格偵測方法特別適用於電子表格匯出、具有一致行列結構的基本資料表格、具有表格資料的報告,以及沒有合併單元格的簡單庫存清單。 如何啟用基本表格的表格偵測? 若要在 IronOCR 中啟用基本表格的表格偵測,請將 ReadDataTables 屬性設定為 true。這會使用 Tesseract 的表格偵測功能,對於單元格邊界清楚且沒有合併單元格的表格效果很好。 圖書館能否處理複雜佈局的發票和財務報告? 是的,IronOCR 的 ReadDocumentAdvanced 方法專門用於處理複雜的文件,例如發票和財務報告。它使用經過訓練的機器學習模型,從具有合併單元格和複雜格式的表格中檢測並擷取資料。 Curtis Chau 立即與工程團隊聊天 技術撰稿人 Curtis Chau 擁有電腦科學學士學位(卡爾頓大學),專長於前端開發,精通 Node.js、TypeScript、JavaScript 和 React。Curtis 對製作直覺且美觀的使用者介面充滿熱情,他喜歡使用現代化的架構,並製作結構良好且視覺上吸引人的手冊。除了開發之外,Curtis 對物聯網 (IoT) 也有濃厚的興趣,他喜歡探索整合硬體與軟體的創新方式。在空閒時間,他喜歡玩遊戲和建立 Discord bots,將他對技術的熱愛與創意結合。 審核人 Jeffrey T. Fritz 首席計畫經理 - .NET 社群團隊 Jeff 也是 .NET 和 Visual Studio 團隊的首席計畫經理。他是 .NET Conf 虛擬會議系列的執行製作人,並主持「Fritz and Friends」開發人直播串流,每週播出兩次,與觀眾一起討論技術和編寫程式碼。Jeff 為 Microsoft Build、Microsoft Ignite、.NET Conf 和 Microsoft MVP Summit 等大型 Microsoft 開發人員活動撰寫工作坊、簡報和規劃內容。 準備好開始了嗎? Nuget 下載 5,384,824 | 版本: 2026.2 剛剛發布 免費 NuGet 下載 總下載量:5,384,824 查看許可證