USO DE IRONPDF

Cómo leer una tabla PDF en C#

Extraer datos de tabla estructurados de documentos PDF es una necesidad frecuente para los desarrolladores de C#, crucial para el análisis de datos, la generación de informes o la integración de información en otros sistemas. Sin embargo, los PDF están diseñados principalmente para una presentación visual consistente, no para una extracción de datos sencilla. Esto puede hacer que la lectura de tablas desde archivos PDF de manera programática en C# sea una tarea desafiante, especialmente dado que las tablas pueden variar ampliamente: desde cuadrículas simples basadas en texto hasta diseños complejos con celdas combinadas, o incluso tablas incrustadas como imágenes en documentos escaneados.

Esta guía ofrece un tutorial completo en C# sobre cómo abordar la extracción de tablas PDF usando IronPDF. Exploraremos principalmente cómo aprovechar las potentes capacidades de extracción de texto de IronPDF para acceder y luego analizar datos tabulares de PDFs basados en texto. Discutiremos la efectividad de este método, proporcionaremos estrategias para el análisis sintáctico y ofreceremos ideas sobre cómo manejar la información extraída. Además, abordaremos estrategias para enfrentar escenarios más complejos, incluidos los PDFs escaneados.


Pasos clave para extraer datos de tablas de PDFs en C#

  1. Instala la biblioteca IronPDF C# (https://nuget.org/packages/IronPdf/) para el procesamiento de PDF.

  2. (Paso opcional de demostración) Crea un PDF de muestra con una tabla a partir de una cadena HTML usando RenderHtmlAsPdf de IronPDF. (Vea la sección: (Demo Paso) Crear un Documento PDF con Datos de Tabla)

  3. Carga cualquier documento PDF y utiliza el método ExtractAllText para obtener su contenido de texto sin formato. (Ver sección: Extraer todo el texto que contiene datos de la tabla del PDF)

  4. Implemente la lógica de C# para analizar el texto extraído e identificar las filas y celdas de la tabla. (Ver sección: Análisis de texto extraído para reconstruir datos de tabla en C#)

  5. Salga los datos estructurados de la tabla o guárdelos en un archivo CSV para su uso posterior. (Ver sección: Análisis de texto extraído para reconstruir datos de tabla en C#)

  6. Considere técnicas avanzadas como OCR para PDFs escaneados (discutido más adelante).


IronPDF - Biblioteca PDF de C#

IronPDF es una solución de biblioteca de .NET en C# para la manipulación de PDF en .NET (https://ironpdf.com/), que ayuda a los desarrolladores a leer, crear y editar documentos PDF fácilmente en sus aplicaciones de software. Su robusto motor Chromium renderiza documentos PDF a partir de HTML con alta precisión y velocidad. Permite a los desarrolladores convertir de distintos formatos a PDF y viceversa sin problemas. Es compatible con los últimos marcos de .NET, incluyendo .NET 7, .NET 6, 5, 4, .NET Core y Standard.

Además, la API de IronPDF .NET también permite a los desarrolladores manipular y editar PDFs, agregar encabezados y pies de página, y, lo que es importante, extraer texto, imágenes y (como veremos) datos de tablas de PDFs con facilidad.

Algunas características importantes incluyen:

Pasos para extraer datos de tablas en C# utilizando la biblioteca IronPDF

Para extraer datos de tablas de documentos PDF, configuraremos un proyecto en C#:

  1. Visual Studio: Asegúrate de tener instalado Visual Studio (por ejemplo, 2022). Si no, descárgalo del sitio web de Visual Studio (https://visualstudio.microsoft.com/downloads/).

  2. Crear Proyecto:

    • Abra Visual Studio 2022 y haga clic en Crear un nuevo proyecto.

    Cómo leer una tabla PDF en C#, Figura 1: Pantalla de inicio de Visual Studio

    Pantalla de inicio de Visual Studio

    • Seleccione "Aplicación de consola" (o su tipo de proyecto C# preferido) y haga clic en Siguiente.

    Cómo Leer una Tabla PDF en C#, Figura 2: Crear una nueva Aplicación de Consola en Visual Studio

    Cree una nueva aplicación de consola en Visual Studio

    • Nombre su proyecto (p. ej., "ReadPDFTableDemo") y haga clic en Siguiente.

    Cómo leer una tabla PDF en C#, Figura 3: Configurar la aplicación recién creada

    Configurar la aplicación recién creada

    • Elige el .NET Framework que desees (por ejemplo, .NET 6 o posterior).

      How to Read PDF Table in C#, Figure 4: Select a .NET Framework

    Seleccione un .NET Framework

    • Haz clic en Crear. Se creará el proyecto de consola.
  3. Instalar IronPDF:

    • Uso del Administrador de Paquetes NuGet de Visual Studio:

      • Haz clic derecho en tu proyecto en el Explorador de soluciones y selecciona "Administrar paquetes NuGet..."

    Cómo leer una tabla PDF en C#, Figura 5: Herramientas y gestionar paquetes NuGet

    Herramientas y administrar paquetes NuGet

    • En el Administrador de paquetes de NuGet, busque "IronPdf" y haga clic en "Instalar".

    Cómo leer tablas en PDF en C#, Figura 6: Herramientas y administrar paquetes NuGet

    Herramientas y administrar paquetes NuGet

(Paso de demostración) Crear un documento PDF con datos de tabla

Para este tutorial, primero crearemos un PDF de muestra que contiene una tabla simple a partir de una cadena HTML. Esto nos proporciona una estructura de PDF conocida para demostrar el proceso de extracción. En un escenario del mundo real, cargarías tus archivos PDF preexistentes.

Agregue el espacio de nombres de IronPDF y opcionalmente configure su clave de licencia (IronPDF es gratuito para el desarrollo, pero requiere una licencia para el despliegue comercial sin marcas de agua):

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";
$vbLabelText   $csharpLabel

Aquí está la cadena HTML para nuestra tabla de ejemplo:

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>";
HTML

Ahora, utiliza ChromePdfRenderer para crear un PDF a partir de este HTML:

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.")
$vbLabelText   $csharpLabel

El método SaveAs guarda el PDF. El table_example.pdf generado se verá así (imagen conceptual basada en HTML):

Cómo Leer una Tabla PDF en C#, Figura 7: Buscar IronPDF en el Administrador de Paquetes NuGet UI

Buscar IronPDF en el Administrador de Paquetes NuGet UI

Extraer todo el texto que contiene datos de la tabla del PDF

Para extraer datos de tablas, primero cargamos el PDF (ya sea el que acabamos de crear o cualquier PDF existente) y utilizamos el método ExtractAllText. Este método recupera todo el contenido textual de las páginas 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()
$vbLabelText   $csharpLabel

La variable allText ahora contiene todo el contenido de texto del PDF. Puedes mostrarlo para ver la extracción en bruto:

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)
$vbLabelText   $csharpLabel

Cómo leer una tabla PDF en C#, Figura 8: El archivo PDF para extraer texto

El archivo PDF para extraer texto

Analizar texto extraído para reconstruir datos de tabla en C#

Con el texto en bruto extraído, el siguiente desafío es analizar esta cadena para identificar y estructurar los datos tabulares. Este paso depende en gran medida de la consistencia y el formato de las tablas en sus PDFs.

Estrategias Generales de Análisis:

  1. Identificar delimitadores de filas: Los caracteres de nueva línea (\n o \r\n) son separadores de filas comunes.

  2. Identificar delimitadores de columna: Las celdas dentro de una fila pueden estar separadas por múltiples espacios, pestañas o caracteres específicos conocidos (como ' ' o ';'). A veces, si las columnas están visualmente alineadas pero carecen de delimitadores de texto claros, podrías inferir la estructura basándote en patrones de espaciado consistentes, aunque esto es más complejo.

  3. Filtrar contenido no tabular: El método ExtractAllText obtiene todo el texto. Necesitarás lógica para aislar el texto que realmente forma tu tabla, posiblemente buscando palabras clave de encabezado o saltando el texto de preámbulo/posámbulo.

    El método String.Split de C# es una herramienta básica para esto. A continuación se muestra un ejemplo que intenta extraer solo las líneas de la tabla de nuestra muestra, filtrando las líneas con puntos (una heurística simple para este ejemplo específico):

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
$vbLabelText   $csharpLabel

Este código divide el texto en líneas. La condición if es un filtro muy básico para el texto no tabulado de este ejemplo específico. En escenarios del mundo real, necesitarías una lógica más robusta para identificar y analizar filas y celdas de tablas con precisión.

Salida del texto filtrado simple:

Cómo leer una tabla PDF en C#, Figura 9: La consola muestra textos extraídos

La consola muestra los textos extraídos

Consideraciones importantes para el método de análisis de texto:

  • Mejor adecuado para: PDFs basados en texto con estructuras de tablas simples, consistentes y delimitadores textuales claros.
  • Limitaciones: Este método puede tener dificultades con:

    • Tablas con celdas combinadas o estructuras anidadas complejas.

    • Tablas donde las columnas están definidas por el espaciado visual en lugar de delimitadores de texto.

    • Tablas incrustadas como imágenes (requiriendo OCR).

    • Variaciones en la generación de PDF que llevan a un orden inconsistente de extracción de texto.

    Puedes guardar las líneas filtradas (que idealmente representan filas de una tabla) en un archivo 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")
$vbLabelText   $csharpLabel

Estrategias para la Extracción de Tablas PDF más Complejas en C#

Extraer datos de tablas PDF complejas o basadas en imágenes a menudo requiere técnicas más avanzadas que el simple análisis de texto. IronPDF proporciona características que pueden ayudar:

  • Usando las capacidades de IronOCR para tablas escaneadas: Si las tablas están dentro de imágenes (por ejemplo, PDFs escaneados), ExtractAllText() por sí solo no las capturará. La funcionalidad de detección de texto de IronOCR puede convertir primero estas imágenes en texto.
// 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
$vbLabelText   $csharpLabel

Para obtener orientación detallada, visite la documentación de IronOCR (https://ironsoftware.com/csharp/ocr/). Después de OCR, analizarías la cadena de texto resultante.

  • Extracción de Texto Basada en Coordenadas (Avanzada): Aunque ExtractAllText() de IronPDF proporciona el flujo de texto, algunos escenarios pueden beneficiarse al conocer las coordenadas x,y de cada fragmento de texto. Si IronPDF ofrece APIs para obtener texto con su información de cuadro delimitador (consulte la documentación actual), esto podría permitir un análisis espacial más sofisticado para reconstruir tablas basadas en la alineación visual.
  • Convertir PDF a otro formato: IronPDF puede convertir PDFs a formatos estructurados como HTML. A menudo, analizar una tabla HTML es más sencillo que analizar texto crudo de PDF.
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.
$vbLabelText   $csharpLabel
  • Reconocimiento de patrones y expresiones regulares: Para tablas con patrones muy predecibles pero con delimitadores inconsistentes, las expresiones regulares complejas aplicadas al texto extraído a veces pueden aislar los datos de la tabla.

    Elegir la estrategia correcta depende de la complejidad y consistencia de tus PDFs de origen. Para muchos documentos comerciales comunes con tablas basadas en texto, ExtractAllText de IronPDF combinado con lógica de análisis inteligente en C# puede ser muy efectivo. Para tablas basadas en imagen, sus capacidades de OCR son esenciales.

Resumen

Este artículo demostró cómo extraer datos de tabla de un documento PDF en C# usando IronPDF, centrándose principalmente en aprovechar el método ExtractAllText() y el análisis posterior de cadenas. Hemos visto que si bien este enfoque es poderoso para tablas basadas en texto, se pueden abordar escenarios más complejos como tablas basadas en imágenes utilizando las características OCR de IronPDF o convirtiendo los PDFs a otros formatos primero.

IronPDF proporciona un conjunto de herramientas versátil para desarrolladores de .NET, simplificando muchas tareas relacionadas con PDF, desde la creación y edición hasta la extracción de datos exhaustiva. Ofrece métodos como DOCX a PDF.

IronPDF es gratuito para el desarrollo y ofrece una licencia de prueba gratuita para probar sus características comerciales completas. Para el despliegue en producción, se encuentran disponibles varias opciones de licencia.

Para obtener más detalles y casos de uso avanzados, explore la documentación oficial de IronPDF y los ejemplos (https://ironpdf.com/)

Chipego
Ingeniero de software
Chipego tiene una habilidad natural para escuchar que le ayuda a comprender los problemas de los clientes y a ofrecer soluciones inteligentes. Se unió al equipo de Iron Software en 2023, después de estudiar una licenciatura en Tecnología de la Información. IronPDF e IronOCR son los dos productos en los que Chipego se ha centrado, pero su conocimiento de todos los productos crece día a día, a medida que encuentra nuevas formas de ayudar a los clientes. Disfruta de lo colaborativa que es la vida en Iron Software, con miembros del equipo de toda la empresa que aportan su variada experiencia para contribuir a soluciones eficaces e innovadoras. Cuando Chipego está lejos de su escritorio, a menudo se le puede encontrar disfrutando de un buen libro o jugando al fútbol.
< ANTERIOR
Cómo convertir un código QR a PDF
SIGUIENTE >
Tutorial de C#: Crear un visor de contenido de texto PDF con IronPDF (Windows Forms)