DEV Community

Allen Yang
Allen Yang

Posted on

How to Export a DataTable to PDF in C#

Generating reports, invoices, or any form of structured documentation from tabular data is a common requirement in many business applications. Often, this data resides within a C# DataTable object. The challenge, however, lies in programmatically taking this C# DataTable and transforming it into a professional, shareable PDF document. Direct rendering of DataTable contents to PDF isn't inherently supported by the .NET framework, necessitating a robust solution.

This article provides a practical, step-by-step guide on how to efficiently export your DataTable to PDF using C#. We will explore how to leverage a powerful third-party library to streamline this process, enabling you to generate dynamic and well-formatted PDF reports with ease.

Understanding the Need for Programmatic PDF Generation

When developing C# applications, data is frequently managed in DataTable objects due to their flexibility and integration with database operations. While displaying this data in a UI control like a DataGridView is straightforward, converting it into a static, distributable format like PDF presents a different challenge. PDFs are ideal for reporting because they maintain formatting across different platforms and are universally accepted for official documents.

The core issue is that a DataTable is an in-memory representation of data, lacking any inherent rendering capabilities for document formats. To bridge this gap, developers typically rely on specialized PDF generation libraries. These libraries provide APIs to create PDF documents from scratch, allowing you to define pages, add text, images, and, crucially for our purpose, convert tabular data into structured PDF tables. Without such a library, you'd be faced with the arduous task of manually drawing every line, character, and cell, which is both complex and time-consuming.

Setting Up Your C# Project for PDF Export

Before we can begin converting our DataTable to PDF, we need to set up our C# project and install the necessary tools. This guide assumes you are working with a .NET project, such as a Console Application or an ASP.NET Core project.

Here's how to get started:

  1. Create a New C# Project:
    Open Visual Studio (or your preferred C# IDE) and create a new project. For this tutorial, a Console Application will suffice, but the principles apply to other project types as well.

  2. Install the PDF Generation Library:
    We will be using a robust PDF component that simplifies the entire process. This library can be easily installed via the NuGet Package Manager.

*   **Using NuGet Package Manager Console:**
    Go to `Tools` > `NuGet Package Manager` > `Package Manager Console`. In the console, type the following command and press Enter:
Enter fullscreen mode Exit fullscreen mode
    ```csharp
    Install-Package Spire.PDF
    ```
Enter fullscreen mode Exit fullscreen mode
*   **Using NuGet Package Manager UI:**
    Right-click on your project in the Solution Explorer, select `Manage NuGet Packages...`. In the Browse tab, search for `Spire.PDF`, select the package, and click `Install`.

This command will download and add the `Spire.PDF` library and its dependencies to your project, making its functionalities available for use.
Enter fullscreen mode Exit fullscreen mode
  1. Add Necessary using Directives:
    In your C# code file (e.g., Program.cs), you'll need to include the following using statements at the top to access the Spire.PDF classes and other relevant .NET functionalities:

    using System;
    using System.Data;
    using Spire.Pdf;
    using Spire.Pdf.Graphics;
    using Spire.Pdf.Tables;
    using System.Drawing; // For Color and PointF
    

    With these steps completed, your project is now ready to begin the DataTable to PDF conversion.

Implementing DataTable to PDF Conversion Logic

This section will walk you through the core logic of converting your C# DataTable into a professional PDF document.

3.1: Preparing Your DataTable (Example Data)

First, let's create a sample DataTable with some dummy data. This DataTable will serve as the source for our PDF report. For demonstration purposes, we'll create a table representing a list of products.

public static DataTable GetSampleDataTable()
{
    DataTable dataTable = new DataTable("Products");

    // Define Columns
    dataTable.Columns.Add("ProductID", typeof(int));
    dataTable.Columns.Add("ProductName", typeof(string));
    dataTable.Columns.Add("Category", typeof(string));
    dataTable.Columns.Add("UnitPrice", typeof(decimal));
    dataTable.Columns.Add("UnitsInStock", typeof(int));

    // Add Sample Rows
    dataTable.Rows.Add(1, "Chai", "Beverages", 18.00m, 39);
    dataTable.Rows.Add(2, "Chang", "Beverages", 19.00m, 17);
    dataTable.Rows.Add(3, "Aniseed Syrup", "Confections", 10.00m, 13);
    dataTable.Rows.Add(4, "Chef Anton's Cajun Seasoning", "Condiments", 22.00m, 53);
    dataTable.Rows.Add(5, "Chef Anton's Gumbo Mix", "Condiments", 21.35m, 0);
    dataTable.Rows.Add(6, "Grandma's Boysenberry Spread", "Condiments", 25.00m, 120);
    dataTable.Rows.Add(7, "Uncle Bob's Organic Dried Pears", "Produce", 30.00m, 15);
    dataTable.Rows.Add(8, "Northwoods Cranberry Sauce", "Condiments", 40.00m, 6);

    return dataTable;
}
Enter fullscreen mode Exit fullscreen mode

This GetSampleDataTable() method will provide the structured data that we intend to export to PDF.

3.2: Using Spire.PDF to Create a PDF Table from DataTable

Now, let's integrate our DataTable into a PDF document using Spire.PDF. The library provides a PdfTable class specifically designed to handle tabular data.

public static void ExportDataTableToPdf(DataTable dataTable, string filePath)
{
    // Create a new PDF document
    PdfDocument doc = new PdfDocument();
    PdfPageBase page = doc.Pages.Add();

    // Add a title to the document
    string title = "Product Inventory Report";
    PdfFont titleFont = new PdfFont(PdfFontFamily.Helvetica, 20f, PdfFontStyle.Bold);
    SizeF titleSize = titleFont.MeasureString(title);
    float titleX = (page.Canvas.ClientSize.Width - titleSize.Width) / 2;
    page.Canvas.DrawString(title, titleFont, PdfBrushes.DarkBlue, titleX, 20);

    // Create a PdfTable instance
    PdfTable pdfTable = new PdfTable();

    // Set the data source for the PdfTable
    pdfTable.DataSource = dataTable;

    // Optional: Customize table appearance
    pdfTable.Style.DefaultStyle.Font = new PdfFont(PdfFontFamily.Helvetica, 10f);
    pdfTable.Style.HeaderStyle.Font = new PdfFont(PdfFontFamily.Helvetica, 11f, PdfFontStyle.Bold);
    pdfTable.Style.HeaderStyle.BackgroundBrush = PdfBrushes.LightGray;
    pdfTable.Style.ShowHeader = true; // Display table headers

    // Set column widths (optional, Spire.PDF can auto-fit)
    // pdfTable.Columns[0].Width = 80f;
    // pdfTable.Columns[1].Width = 150f;
    // ...

    // Draw the table on the PDF page
    PdfLayoutResult result = pdfTable.Draw(page, new PointF(0, 60)); // Start drawing from Y=60 (below title)

    // Save the document
    doc.SaveToFile(filePath);
    doc.Close();
}
Enter fullscreen mode Exit fullscreen mode

In this code snippet:

  • We initialize a PdfDocument and add a new page.
  • A title is added to the top of the page for better presentation.
  • We create a PdfTable object and assign our dataTable to its DataSource property. This is the crucial step where Spire.PDF automatically maps the DataTable's columns and rows into a PDF table structure.
  • Basic styling is applied to the table, including default font, header font, and header background color.
  • Finally, pdfTable.Draw() renders the table onto the PDF page at a specified position.

3.3: Enhancing and Saving the PDF Document

Beyond the basic table, you might want to add more formatting or introductory text. Spire.PDF offers extensive options for this.

Let's enhance the ExportDataTableToPdf method to include more detailed styling and ensure proper saving.

public static void ExportDataTableToPdfWithStyle(DataTable dataTable, string filePath)
{
    // Create a new PDF document
    PdfDocument doc = new PdfDocument();
    PdfPageBase page = doc.Pages.Add();

    // Set page margins (optional)
    doc.PageSettings.Margins.All = 40;

    // Add a title
    string title = "Detailed Product Inventory Report";
    PdfFont titleFont = new PdfFont(PdfFontFamily.Helvetica, 24f, PdfFontStyle.Bold);
    SizeF titleSize = titleFont.MeasureString(title);
    float titleX = (page.Canvas.ClientSize.Width - titleSize.Width) / 2;
    page.Canvas.DrawString(title, titleFont, PdfBrushes.DarkBlue, titleX, 20);

    // Add an introductory paragraph
    string introduction = "This report provides an overview of current product inventory levels, detailing product ID, name, category, unit price, and units in stock.";
    PdfFont introFont = new PdfFont(PdfFontFamily.Helvetica, 12f);
    page.Canvas.DrawString(introduction, introFont, PdfBrushes.Black, new PointF(0, 60), new PdfStringFormat(PdfStringFormatFlags.WordBreak) {
        MeasureTrailingSpaces = true
    });

    // Calculate table start position after title and introduction
    float tableY = 60 + introFont.MeasureString(introduction, page.Canvas.ClientSize.Width).Height + 20; // 20 units padding

    // Create PdfTable
    PdfTable pdfTable = new PdfTable();
    pdfTable.DataSource = dataTable;

    // Customize table style
    pdfTable.Style.DefaultStyle.Font = new PdfFont(PdfFontFamily.Helvetica, 9f);
    pdfTable.Style.DefaultStyle.StringFormat = new PdfStringFormat(PdfStringFormatFlags.LineLimit) { LineAlignment = PdfVerticalAlignment.Middle, Alignment = PdfHorizontalAlignment.Center };
    pdfTable.Style.HeaderStyle.Font = new PdfFont(PdfFontFamily.Helvetica, 10f, PdfFontStyle.Bold);
    pdfTable.Style.HeaderStyle.BackgroundBrush = new PdfSolidBrush(Color.FromArgb(120, 180, 230)); // Light blue header
    pdfTable.Style.HeaderStyle.TextBrush = PdfBrushes.White;
    pdfTable.Style.ShowHeader = true;

    // Apply alternating row colors for better readability
    pdfTable.Style.AlternateRowStyle.BackgroundBrush = new PdfSolidBrush(Color.LightYellow);

    // Set cell padding
    pdfTable.Style.DefaultStyle.CellPadding = 5;

    // Set column widths manually (adjust as needed)
    pdfTable.Columns[0].Width = 70f;  // ProductID
    pdfTable.Columns[1].Width = 150f; // ProductName
    pdfTable.Columns[2].Width = 100f; // Category
    pdfTable.Columns[3].Width = 80f;  // UnitPrice
    pdfTable.Columns[4].Width = 90f;  // UnitsInStock

    // Draw the table on the PDF page, handling page breaks automatically
    PdfLayoutResult result = pdfTable.Draw(page, new PointF(0, tableY));

    // Save the document to a file
    doc.SaveToFile(filePath);
    doc.Close();
}
Enter fullscreen mode Exit fullscreen mode

To run this example, you would call it from your Main method:

class Program
{
    static void Main(string[] args)
    {
        DataTable productsTable = GetSampleDataTable();
        string outputPdfPath = "ProductReport.pdf";
        ExportDataTableToPdfWithStyle(productsTable, outputPdfPath);
        Console.WriteLine($"PDF report generated successfully at: {outputPdfPath}");
        Console.ReadKey();
    }

    // Include GetSampleDataTable method here
    public static DataTable GetSampleDataTable()
    {
        // ... (previous GetSampleDataTable code)
        DataTable dataTable = new DataTable("Products");
        dataTable.Columns.Add("ProductID", typeof(int));
        dataTable.Columns.Add("ProductName", typeof(string));
        dataTable.Columns.Add("Category", typeof(string));
        dataTable.Columns.Add("UnitPrice", typeof(decimal));
        dataTable.Columns.Add("UnitsInStock", typeof(int));
        dataTable.Rows.Add(1, "Chai", "Beverages", 18.00m, 39);
        dataTable.Rows.Add(2, "Chang", "Beverages", 19.00m, 17);
        dataTable.Rows.Add(3, "Aniseed Syrup", "Confections", 10.00m, 13);
        dataTable.Rows.Add(4, "Chef Anton's Cajun Seasoning", "Condiments", 22.00m, 53);
        dataTable.Rows.Add(5, "Chef Anton's Gumbo Mix", "Condiments", 21.35m, 0);
        dataTable.Rows.Add(6, "Grandma's Boysenberry Spread", "Condiments", 25.00m, 120);
        dataTable.Rows.Add(7, "Uncle Bob's Organic Dried Pears", "Produce", 30.00m, 15);
        dataTable.Rows.Add(8, "Northwoods Cranberry Sauce", "Condiments", 40.00m, 6);
        return dataTable;
    }
}
Enter fullscreen mode Exit fullscreen mode

Output Preview:

This enhanced version demonstrates adding an introductory paragraph, applying more sophisticated table styling (alternating row colors, custom header brush, cell padding), and explicitly setting column widths for fine-grained control over the layout.

Advanced Considerations and Best Practices

While the above examples cover the basic and styled export, here are some advanced considerations:

  • Handling Large Datasets (Pagination): For DataTables with many rows that exceed a single page, Spire.PDF's PdfTable.Draw method automatically handles pagination. If the table extends beyond the current page's boundaries, it will automatically flow to the next page, creating new pages as needed. You can further control this behavior using PdfLayoutType and PdfLayoutFormat settings.
  • Error Handling: Always wrap file operations (like doc.SaveToFile) in try-catch blocks to gracefully handle potential exceptions such as file access errors or I/O issues.
  • Performance: For extremely large datasets, consider optimizing your DataTable creation and potentially processing data in chunks if memory becomes an issue, although Spire.PDF is generally optimized for performance.
  • Dynamic Column Generation: If your DataTable columns are not fixed, you can dynamically configure PdfTable.Columns based on dataTable.Columns to ensure all data is correctly represented.

Conclusion

Exporting a DataTable to PDF in C# is a common and essential task for many applications. By leveraging a dedicated library like Spire.PDF for .NET, the process becomes remarkably straightforward and efficient. We've covered how to set up your project, prepare your data, and convert it into a well-formatted PDF document with customizable styling.

This approach not only saves development time but also ensures the generation of high-quality, professional PDF reports directly from your C# applications. Implement this solution in your projects to streamline your report generation and enhance your application's data export capabilities.

Top comments (0)