Jak odczytywać tabele w dokumentach za pomocą języka C

This article was translated from English: Does it need improvement?
Translated
View the article in English

IronOCR umożliwia deweloperom C# ekstrakcję danych z tabel w plikach PDF i obrazach za pomocą zaawansowanych modeli uczenia maszynowego, obsługując zarówno proste tabele z podstawowymi komórkami, jak i skomplikowane struktury takie jak faktury ze scalonymi komórkami, używając metody ReadDocumentAdvanced.

Pobieranie danych z tabel przy użyciu zwykłego Tesseracta może być trudne, ponieważ tekst często znajduje się w komórkach i jest rozrzucony po całym dokumencie. Jednak nasza biblioteka zawiera model uczenia maszynowego, który został wyszkolony i dostrojony pod kątem dokładnego wykrywania i wyodrębniania danych z tabel. Niezależnie od tego, czy przetwarzasz raporty finansowe, listy zapasów czy dane z faktur, IronOCR zapewnia narzędzia do wydajnego analizowania danych strukturalnych.

Dla prostych tabel polegaj na łatwym wykrywaniu tabel za pomocą standardowej klasy OcrInput. Dla bardziej złożonych struktur nasza ekskluzywna metoda ReadDocumentAdvanced zapewnia solidne wyniki, skutecznie parsując tabele i dostarczając dane. Ta zaawansowana metoda wykorzystuje uczenie maszynowe do rozpoznawania układów tabel, scalonych komórek i złożonego formatowania, z którymi tradycyjne OCR często ma trudności.

Szybki start: Wyodrębnianie złożonych komórek tabeli za pomocą jednego wywołania

Uruchom się w kilka minut—ten przykład pokazuje, jak jedno wywołanie IronOCR używając ReadDocumentAdvanced daje szczegółowe dane komórek tabeli ze złożonego dokumentu. Demonstruje łatwość użytkowania poprzez wczytanie pliku PDF, zastosowanie zaawansowanego wykrywania tabel i bezpośrednie zwrócenie listy informacji o komórkach.

  1. Install IronOCR with NuGet Package Manager

    PM > Install-Package IronOcr
  2. Skopiuj i uruchom ten fragment kodu.

    var cells = new IronTesseract().ReadDocumentAdvanced(new OcrInput().LoadPdf("invoiceTable.pdf")).Tables.First().CellInfos;
  3. Wdrożenie do testowania w środowisku produkcyjnym

    Rozpocznij używanie IronOCR w swoim projekcie już dziś z darmową wersją próbną

    arrow pointer

Poniższe kroki pomogą Ci rozpocząć pracę z odczytywaniem tabel za pomocą IronOCR:


Jak wyodrębnić dane z prostych tabel?

Ustawienie właściwości ReadDataTables na true umożliwia wykrywanie tabel za pomocą Tesseract. Takie podejście sprawdza się dobrze w przypadku prostych tabel z wyraźnymi granicami komórek i bez komórek połączonych. Aby przetestować tę funkcję, stworzyłem prosty plik PDF z tabelą, który można pobrać tutaj: "simple-table.pdf". Za pomocą tej metody można wykrywać proste tabele bez scalonych komórek. W przypadku bardziej złożonych tabel należy skorzystać z metody opisanej poniżej.

Standardowa metoda wykrywania tabel jest szczególnie skuteczna w przypadku:

  • Eksport do arkuszy kalkulacyjnych
  • Podstawowe tabele danych o spójnej strukturze wierszy i kolumn
  • Raporty zawierające dane tabelaryczne
  • Proste listy inwentarzowe

W przypadku ogólnego wykorzystania funkcji OCR do wyodrębniania tekstu z plików PDF, metoda ta płynnie integruje się z szerszymi możliwościami przetwarzania dokumentów oferowanymi przez 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

Jak odczytać złożone tabele faktur?

Jednym z częściej spotykanych złożonych tabel w środowisku biznesowym są faktury. Faktury to złożone tabele zawierające wiersze i kolumny danych, często z połączonymi komórkami, zmienną szerokością kolumn i strukturami zagnieżdżonymi. Dzięki IronOCR wykorzystujemy metodę ReadDocumentAdvanced, aby skutecznie sobie z nimi radzić. Proces obejmuje skanowanie dokumentu, identyfikację struktury tabeli i wyodrębnianie danych. W tym przykładzie używamy pliku "invoiceTable.PDF", aby pokazać, w jaki sposób IronOCR pobiera wszystkie informacje z faktury.

Metoda ReadDocumentAdvanced wymaga instalacji pakietu IronOcr.Extensions.AdvancedScan obok podstawowego pakietu IronOCR. To rozszerzenie zapewnia zaawansowane możliwości uczenia maszynowego, specjalnie dostosowane do złożonych układów dokumentów.

Zwróć uwagę
Korzystanie z zaawansowanego skanowania w środowisku .NET Framework wymaga, aby projekt działał na architekturze x64. Aby to osiągnąć, przejdź do konfiguracji projektu i odznacz opcję "Preferuj 32-bit". Więcej informacji można znaleźć w poniższym przewodniku dotyczącym rozwiązywania problemów: "Zaawansowane skanowanie w środowisku .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

Metoda ta dzieli dane tekstowe dokumentu na dwie kategorie: jedną otoczoną ramkami, a drugą bez ramek. W przypadku treści w ramkach biblioteka dzieli ją dalej na podsekcje w oparciu o strukturę tabeli. Metoda ta doskonale sprawdza się w obsłudze:

  • Pozycje faktury z różnymi opisami
  • Wielokolumnowe zestawienia cen
  • Bloki adresów wysyłkowych i rozliczeniowych
  • Sekcje dotyczące podatków i obliczeń sumarycznych
  • Informacje w nagłówku i stopce

Wyniki przedstawiono poniżej. Ponieważ ta metoda skupia się na informacjach zawartych w obramowaniach, wszelkie połączone komórki obejmujące wiele wierszy będą traktowane jako pojedyncza komórka.

Jak wyglądają wyodrębnione dane?

IronSoftware OCR wyodrębnia dane tabelaryczne z faktury wysyłkowej do ustrukturyzowanego formatu hierarchicznego

Jak uporządkować i przetworzyć wyodrębnione komórki tabeli?

W obecnej implementacji wyodrębnione komórki nie są jeszcze odpowiednio uporządkowane. Jednak każda komórka zawiera cenne informacje, takie jak współrzędne X i Y, wymiary i inne. Korzystając z tych danych, możemy stworzyć klasę pomocniczą do różnych celów. Informacje w komórce obejmują:

  • Precyzyjne współrzędne X/Y do pozycjonowania
  • Wymiary szerokości i wysokości
  • Treść tekstowa
  • Wyniki pewności
  • Relacje komórek

Te szczegółowe informacje umożliwiają programowe odtworzenie struktury tabeli i zastosowanie niestandardowej logiki do ekstrakcji danych. Można również użyć tych współrzędnych do zdefiniowania konkretnych obszarów do ukierunkowanego przetwarzania OCR w kolejnych operacjach.

Poniżej znajduje się kilka podstawowych metod pomocniczych:

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

Najlepsze praktyki dotyczące ekstrakcji tabel

Podczas pracy z ekstrakcją tabel w IronOCR należy wziąć pod uwagę następujące najlepsze praktyki:

  1. Jakość dokumentu: Dokumenty o wyższej rozdzielczości dają lepsze wyniki. W przypadku dokumentów zeskanowanych należy zapewnić rozdzielczość co najmniej 300 DPI.

  2. Przetwarzanie wstępne: W przypadku dokumentów o niskiej jakości lub z przekrzywionymi tabelami warto rozważyć użycie funkcji korekcji obrazu IronOCR przed przetwarzaniem.

  3. Wydajność: W przypadku dużych dokumentów zawierających wiele tabel warto rozważyć wykorzystanie wielowątkowości i obsługi asynchronicznej w celu równoległego przetwarzania stron.

  4. Opcje wyjściowe: Po wyodrębnieniu danych z tabeli można wyeksportować wyniki w różnych formatach. Dowiedz się więcej o opcjach eksportu danych oraz o tym, jak tworzyć pliki PDF z możliwością wyszukiwania na podstawie przetworzonych dokumentów.

  5. Przetwarzanie strumieniowe: W przypadku aplikacji internetowych lub scenariuszy wykorzystujących dokumenty w pamięci warto rozważyć użycie OCR dla strumieni PDF, aby uniknąć operacji na systemie plików.

Podsumowanie

IronOCR zapewnia zaawansowane możliwości wyodrębniania tabel zarówno dzięki standardowemu wykrywaniu opartemu na Tesseract, jak i zaawansowanym metodom uczenia maszynowego. Standardowe podejście dobrze działa dla prostych tabel, podczas gdy metoda ReadDocumentAdvanced doskonale radzi sobie z dokumentami złożonymi, takimi jak faktury. Dzięki udostępnionym metodom pomocniczym możesz organizować i przetwarzać wyodrębnione dane zgodnie ze swoimi konkretnymi potrzebami.

Poznaj więcej funkcji IronOCR, aby usprawnić procesy przetwarzania dokumentów i w pełni wykorzystać potencjał optycznego rozpoznawania znaków w aplikacjach .NET.

Często Zadawane Pytania

Jak mogę wyodrębnić dane tabeli z PDFów i obrazów w C#?

IronOCR umożliwia programistom C# ekstrakcję danych tabeli z PDFów i obrazów za pomocą zaawansowanych modeli uczenia maszynowego. Dla prostych tabel użyj klasy OcrInput z ustawioną właściwością ReadDataTables na true. Dla złożonych tabel ze scalonymi komórkami użyj metody ReadDocumentAdvanced dla bardziej dokładnych wyników.

Jaka jest różnica między prostą a złożoną ekstrakcją tabeli?

Prosta ekstrakcja tabeli w IronOCR korzysta z właściwości ReadDataTables z Tesseract i działa dobrze dla podstawowych tabel z wyraźnymi granicami komórek. Złożona ekstrakcja tabeli wymaga metody ReadDocumentAdvanced, która używa uczenia maszynowego do obsługi scalonych komórek, faktur i złożonego formatowania.

Jak szybko wyekstrahować dane z złożonych tabel?

Użyj metody ReadDocumentAdvanced w IronOCR w jednym wywołaniu: var cells = new IronTesseract().ReadDocumentAdvanced(new OcrInput().LoadPdf('invoiceTable.pdf')).Tables.First().CellInfos; To wykorzystuje uczenie maszynowe do zrozumienia układów tabeli i złożonego formatowania.

Jakie typy dokumentów najlepiej działają z wykrywaniem prostych tabel?

Metoda wykrywania prostych tabel w IronOCR działa szczególnie dobrze z eksportami arkuszy kalkulacyjnych, podstawowymi tabelami danych z jednolitą strukturą wierszy/kolumn, raportami z danymi tabelarycznymi oraz prostymi listami inwentarzowymi bez scalonych komórek.

Jak włączyć wykrywanie tabeli dla podstawowych tabel?

Aby włączyć wykrywanie tabeli w IronOCR dla podstawowych tabel, ustaw właściwość ReadDataTables na true. To używa możliwości wykrywania tabel Tesseract i działa dobrze dla tabel z wyraźnymi granicami komórek i bez scalonych komórek.

Czy biblioteka obsługuje faktury i raporty finansowe o złożonych układach?

Tak, metoda ReadDocumentAdvanced w IronOCR jest specjalnie zaprojektowana do obsługi złożonych dokumentów, takich jak faktury i raporty finansowe. Używa modeli uczenia maszynowego wyszkolonych do wykrywania i wyodrębniania danych z tabel ze scalonymi komórkami i złożonym formatowaniem.

Curtis Chau
Autor tekstów technicznych

Curtis Chau posiada tytuł licencjata z informatyki (Uniwersytet Carleton) i specjalizuje się w front-endowym rozwoju, z ekspertką w Node.js, TypeScript, JavaScript i React. Pasjonuje się tworzeniem intuicyjnych i estetycznie przyjemnych interfejsów użytkownika, Curtis cieszy się pracą z nowoczesnymi frameworkami i tworzeniem dobrze zorganizowanych, atrakcyjnych wizualnie podrę...

Czytaj więcej
Sprawdzone przez
Jeff Fritz
Jeffrey T. Fritz
Główny Menedżer Programu - Zespół .NET Community
Jeff jest również Głównym Menedżerem Programu dla zespołów .NET i Visual Studio. Jest producentem wykonawczym wirtualnej serii konferencji .NET Conf i prowadzi 'Fritz and Friends', transmisję na żywo dla deweloperów emitowaną dwa razy w tygodniu, gdzie rozmawia o technologii i pisze kod razem z widzami. Jeff pisze warsztaty, prezentacje i planuje treści dla największych wydarzeń Microsoft dla deweloperów, w tym Microsoft Build, Microsoft Ignite, .NET Conf i Microsoft MVP Summit.
Gotowy, aby rozpocząć?
Nuget Pliki do pobrania 5,571,678 | Wersja: 2026.4 just released
Still Scrolling Icon

Wciąż przewijasz?

Czy chcesz szybko dowodu? PM > Install-Package IronOcr
uruchom próbkę obserwuj, jak twój obraz staje się tekstem z możliwością wyszukiwania.