QuestPDF

website·Indexed 33 days ago

https://www.questpdf.com

A modern C# and .NET library for PDF document generation featuring a dedicated layout engine. It provides a fluent API for creating complex documents, including support for accessibility standards (Tagged PDF, PDF/A, PDF/UA), dynamic composition, and a Companion App for real-time document previewing.

Tokens
53.1K
Snippets
243
Records
309
Agent score
69%

What's inside QuestPDF

  1. Overview of QuestPDF Companion App

    The QuestPDF Companion application is a development tool that provides a real-time preview of PDF documents. Its primary feature is hot-reload capability, which observes code changes and updates the document preview automatically without requiring full code recompilation.
  2. QuestPDF Current Development and Future Roadmap

    QuestPDF is actively expanding its capabilities in the following areas:

    In Progress:

    • New layout elements, configuration options, and engine enhancements.
    • Expansion to runtimes and languages beyond .NET.
    • New introductory video and learning materials.

    Upcoming (Up Next):

    • A sample gallery with ready-to-use code for common documents (invoices, reports, certificates).
    • Expanded documentation with more end-to-end examples and advanced guidance.

    Future Plans:

    • Validation & Compliance: Built-in PDF validation via veraPDF; support for PDF/A-4 and PDF/UA-2 standards.
    • Security & Internationalization: Digital signing with X.509 certificates and content translation tooling.
    • Interactive & Analysis Features: Basic AcroForm support (interactive fields) and PDF content inspection (text/structure extraction).
    • Stability: Increased automated test coverage and ongoing performance/resource-efficiency optimizations.
  3. Arrange elements sequentially with the Inlined component

    The Inlined component arranges elements sequentially in a line and automatically wraps them to the next line when the container width is exceeded. This is ideal for displaying collections of elements horizontally with consistent spacing and alignment.
    .Inlined(inlined =>
    {
        inlined.Spacing(25);
        inlined.BaselineMiddle();
        inlined.AlignCenter();
        
        foreach (var _ in Enumerable.Range(0, 15))
            inlined.Item().Element(RandomBlock);
    });
  4. Implement a three-layer architecture for QuestPDF documents

    QuestPDF recommends a three-layer architecture to ensure maintainability and clarity when generating PDF documents:

    1. Document Models: Plain C# classes that define the raw data to be displayed (e.g., invoice details), free of business logic.
    2. Data Source: A layer responsible for asynchronous data fetching, database queries, mapping domain entities to document models, and loading external resources like images.
    3. Template: The visual design layer using the QuestPDF Fluent API and C# features (loops, conditionals) to define the layout and appearance.
  5. Arrange content vertically using the Column element

    The Column element stacks items vertically one below another. It supports automatic paging, meaning content flows naturally across multiple pages and child items are split across pages to prevent content from being cut off.
    container
        .Width(250)
        .Padding(25)
        .Column(column =>
        {
            column.Item().Background(Colors.Grey.Medium).Height(50);
            column.Item().Background(Colors.Grey.Lighten1).Height(75);
            column.Item().Background(Colors.Grey.Lighten2).Height(100);
        });
  6. Position child content using Alignment

    The Alignment element in QuestPDF controls how child content is positioned within the available space of a container. It provides independent methods for horizontal and vertical alignment which can be combined to achieve specific positioning (e.g., bottom-center).
  7. Integrate ScottPlot for charting in QuestPDF

    QuestPDF provides charting capabilities by integrating with the ScottPlot library. Charts are rendered as vector graphics via dynamically generated SVG content, ensuring they remain sharp at any scale. The ScottPlot library is not included in the QuestPDF package and must be installed separately via NuGet.
    # Install ScottPlot via NuGet package manager
    dotnet add package ScottPlot
  8. Understand QuestPDF default font behavior

    QuestPDF includes the Lato font (version 2.015) by default to ensure successful document generation. This font covers Latin, Greek, and Cyrillic scripts. If your document requires other writing systems, you must provide additional fonts.
  9. Understand PDF Accessibility Standards (Tagged PDF, PDF/A, PDF/UA)

    PDF accessibility ensures documents are usable by people with disabilities via assistive technologies (screen readers, braille displays). It relies on a hidden logical structure rather than visual layout.

    • Tagged PDF: The foundation of accessibility. It uses hidden structural metadata (tags) similar to semantic HTML (e.g., <h1>, <p>) to define the meaning and reading order of content.
    • PDF/A (Archival): ISO 19005 standard for long-term preservation. Levels like PDF/A-2a and PDF/A-3a require the document to be a Tagged PDF.
    • PDF/UA (Universal Accessibility): ISO 14289 is the gold standard for accessibility. It specifies exactly how a PDF must be structured to be fully accessible. QuestPDF accessibility features aim to meet this standard.
  10. Use Page slots to define document layout in QuestPDF

    The Page container in QuestPDF is a multi-child container used to define the layout of a page. It provides specific slots to organize content into headers, footers, main content, and layering overlays (foreground/background).
  11. Create a basic table in QuestPDF

    The Table component organizes content into rows and columns. To create a table, you must first define the columns using ColumnsDefinition and then add cells. Cells are added sequentially; once the number of defined columns is reached, QuestPDF automatically starts a new row.
    .Table(table =>
    {
        table.ColumnsDefinition(columns =>
        {
            columns.ConstantColumn(50);
            columns.RelativeColumn();
            columns.ConstantColumn(125);
        });
    
        table.Header(header =>
        {
            header.Cell().BorderBottom(2).Padding(8).Text("#");
            header.Cell().BorderBottom(2).Padding(8).Text("Product");
            header.Cell().BorderBottom(2).Padding(8).AlignRight().Text("Price");
        });
        
        foreach (var i in Enumerable.Range(0, 6))
        {
            var price = Math.Round(Random.Shared.NextDouble() * 100, 2);
             
            table.Cell().Padding(8).Text($"{i + 1}");
            table.Cell().Padding(8).Text(Placeholders.Label());
            table.Cell().Padding(8).AlignRight().Text($"${price}");
        }
    });
  12. Create document navigation with Sections and SectionLinks

    In QuestPDF, a Section defines a named fragment of a document that can span multiple pages, which is essential for creating tables of contents and document navigation. To allow users to jump to a specific section, use a SectionLink, which creates a clickable area that navigates to the designated section name. Additionally, you can dynamically display the page number where a specific section begins using the BeginPageNumberOfSection method within a text span.
    Document.Create(document =>
    {
        document.Page(page =>
        {
            page.Content().Column(column =>
            {
                // 1. Create a SectionLink in the Table of Contents
                column.Item()
                    .SectionLink("my-section-id")
                    .Text(text =>
                    {
                        text.Span("Go to Section ");
                        // 2. Display the page number where the section starts
                        text.BeginPageNumberOfSection("my-section-id");
                    });
    
                column.Item().PageBreak();
    
                // 3. Define the target Section
                column.Item()
                    .Section("my-section-id")
                    .Text("This is the target content.");
            });
        });
    }).GeneratePdf("output.pdf");