Create PDF documents in C# and VB.NET

Do you, as a .NET developer, need to generate PDF reports, invoices, receipts or other documents? Use Docotic.Pdf library to generate PDF documents in your .NET Core, .NET Standard, or .NET Framework projects. You can do this easily and without knowing about PDF format at all.

Create PDF documents in C# and VB.NET

.NET API for PDF generation

Docotic.Pdf is the 100% managed code library without external dependencies. You can use it to create PDF documents on Windows, Linux, Amazon and Azure cloud environments. macOS, iOS, Android, and other cloud environments are fine, too.

The library provides different ways for generating PDF documents. First, you can use the high-level layout API to add page headers and footers, tables, paragraphs, and automatically break content to pages. The layout API is available in the free Docotic.Pdf.Layout add-on.

Or you can create PDF documents based on HTML templates using the HTML to PDF add-on (also free). Read the Convert HTML to PDF article for more detail.

And you can produce PDF documents using the core library API. It supports any PDF content - text, images, vector graphics, forms, annotations, bookmarks, layers, and others. However, the core API does not support high-level layout components, such as headers, tables, sections. With the core library, you will need to measure content and split it between PDF pages yourself.

You can also use add-ons with the core library together. For example, generate the PDF document using the layout API and then add more content with the core library. Note that the layout add-on supports .NET Standard 2.1, .NET Core, .NET 5 and newer frameworks. The core library and the HTML to PDF add-on support .NET Standard 2.0, .NET 4.7.2+, .NET Core, .NET 5 and newer.

Docotic.Pdf add-ons are available on NuGet and included in the zip with binaries of the library. To try the library without evaluation mode restrictions, you may get the free time-limited license key here.

Create PDF documents using the layout API

This C# sample shows how to generate a PDF document in C# using the layout API:

PdfDocumentBuilder
    .Create()
    .Generate("long-text.pdf", doc => doc.Pages(page =>
    {
        string text = File.ReadAllText(@"C# in Depth, Fourth Edition.txt");
        page.Content().Text(text);

        page.Footer().AlignCenter().Text(t => t.CurrentPageNumber());
    }));

The code converts a text file to a PDF. It splits long text to pages and also draws page numbers in the footer area. You do not need to calculate text height or count pages - the library takes care of these routine tasks.

The layout API is a fluent API. Most calls can be chained together, so you can write more compact code than with "declarative" frameworks. Let's review the API in more detail.

Set PDF document properties

PDF generation starts with the PdfDocumentBuilder class. It allows you to specify properties of a generated PDF document. For example, you can set metadata, encryption, PDF version, or enable fast web view. Here is the basic C# sample:

PdfDocumentBuilder
    .Create()
    .Encryption(new PdfStandardEncryptionHandler("owner", "user"))
    .Info(info =>
    {
        info.Author = "Docotic.Pdf library";
        info.Title = "How to create PDF in .NET";
        info.Keywords = "C#, VB.NET";
    })
    .Version(PdfVersion.Pdf16)
    .Generate("result.pdf", doc => doc.Pages(_ => {}));

This sample creates an empty password-protected PDF document with custom metadata and saves it to a file. You can also save the document to a stream, just use the PdfDocumentBuilder.Generate(Stream, ..) overload.

When you set up a PdfDocumentBuilder, it's time to populate the PDF document with content. The layout API provides a Document object for registering common resources (typography, images) and defining PDF page content. You can configure a Document in the second argument of PdfDocumentBuilder.Generate methods. Let's learn how to set up PDF pages.

Define PDF page layout

This C# sample shows how to create a PDF document with A3 pages in landscape orientation:

PdfDocumentBuilder.Create().Generate("pages.pdf", doc =>
{
    doc.Pages((PageLayout page) =>
    {
        page.Size(PdfPaperSize.A3, PdfPaperOrientation.Landscape)
            .MarginVertical(50)
            .MarginHorizontal(40);

        page.Header().PaddingBottom(30).AlignRight().Text("Hello PDF");

        page.Content().Column(c =>
        {
            c.Item().Text("Page 1");
            c.Item().PageBreak();
            c.Item().Text("Page 2");
        });

        page.Footer().Text(t => t.CurrentPageNumber());
    });
});

The Document.Pages() method defines layout for one or more pages. First, the sample code sets common settings for all pages - size, orientation, margins. You can also specify content direction, default text style, or background color.

Then, the sample generates the page layout and content. The PageLayout class provides methods for placing page content in the following slots:

  • Background() - a background layer covered by other content
  • Header() - a common header for all pages
  • Content() - a main page content
  • Footer() - a common footer for all pages
  • Foreground() - a foreground layer that covers other content

The layout engine generates pages depending on the content added to the PageLayout.Content() slot. Other slots are repeated on every page. You can add content to slots using the LayoutContainer class. This is a key building block of the layout API, which allows you to generate arbitrary layouts, tables, text, or images.

The previous sample uses the LayoutContainer.Column method that vertically stacks content. That column contains 3 items - the text chunk for the first page, the explicit page break, and the text chunk for the second page.

There is also the LayoutContainer.Row method. Look how to create multi-column PDF documents using rows and columns together.

You can mix different page layouts in a PDF document. Just call the Document.Pages method multiple times. Look at the PDF page layout settings sample on GitHub for an example.

Add text to PDF documents

Text is an important part of PDF documents. You can use LayoutContainer.Text methods to add text. Earlier, you saw use cases for the LayoutContainer.Text(string) overload. Let's look at another overload of this method:

PdfDocumentBuilder.Create().Generate("text.pdf", doc =>
{
    doc.Pages(p => p.Content().Text(text =>
    {
        text.Span("VB.NET").Style(t => t.Strong);
        text.Span(" is a multi-paradigm, object-oriented programming language, implemented on.NET, Mono, and the ");
        text.Hyperlink(".NET Framework", new Uri("https://dotnet.microsoft.com/en-us/download/dotnet-framework"));
        text.Line(".");

        text.Line("Microsoft launched VB.NET in 2002 as the successor to its original Visual Basic language.");
    }));
});

The TextContainer class provides methods to draw text, links, page numbers. Use Span and Line methods to add text to a current line. The Line method additionally completes the current line. This sample also uses the Hyperlink method that adds an external resource link.

Here is another sample showing how to use dynamic page numbers in a page footer:

PdfDocumentBuilder.Create().Generate("footer.pdf", doc =>
{
    doc.Pages(p => p.Footer().AlignRight().Text(text =>
    {
        text.Style(t => t.Parent.FontColor(new PdfRgbColor(255, 0, 0)));

        text.CurrentPageNumber();
        text.Span(" / ");
        text.PageCount();
    }));
});

The layout API provides a way to format page numbers. For example, you can draw hexadecimal page numbers like that:

text.CurrentPageNumber().Format(p => "0x" + p?.ToString("x2"));

The Add header and footer to PDF documents in C# and VB.NET sample shows how to format page numbers as Roman numerals.

You might see that the samples above use the Style method. Let's research the concept of text styles in more detail.

Typography

Text styles allow you to customize text appearance. The TextStyle class provides methods to change font size, letter spacing, colors, and other text properties. TextStyle objects are immutable, so every method call produces a new text style. You can apply text style on different layout levels:

PdfDocumentBuilder.Create().Generate("text-styles.pdf", doc =>
{
    doc.Pages(page =>
    {
        page.TextStyle(TextStyle.Parent.FontSize(30));

        page.Content()
            .TextStyle(TextStyle.Parent.FontColor(new PdfRgbColor(0, 0, 255)))
            .Text(t =>
            {
                t.Style(TextStyle.Parent.Underline());

                t.Span("Hello PDF").Style(TextStyle.Parent.DirectionRightToLeft());
            });
    });
});

The TextStyle.Parent property returns a special style with all text properties undefined. The previous sample draws "Hello PDF" as blue, underlined, 30 points font size in a reverse order (from right to left). Look at the Customize text appearance in PDF documents sample for another text style inheritance example.

The TextStyle class supports customizing everything except an associated font. Use Document.TextStyleWithFont methods when you need to specify a custom font for your text style. This C# sample shows how to use a system font:

PdfDocumentBuilder.Create().Generate("fonts.pdf", doc =>
{
    doc.Pages(page =>
    {
        TextStyle style = doc.TextStyleWithFont(SystemFont.Family("Arial").Bold());
        page.Content().Text("Bold text").Style(style);
    });
});

The layout engine removes unused font glyphs by default. Because of this, generated documents might have a small size even for large fonts. You can also specify a custom font loader, fallback fonts, handler for missing glyphs. Look at the Use different fonts in PDF documents sample for more detail.

The layout API provides a collection of predefined styles. You can use or customize them via the Typography class:

PdfDocumentBuilder.Create().Generate("typography.pdf", doc =>
{
    doc.Typography(t =>
    {
        var baseFont = new FileInfo("arial.ttf");
        t.Document = doc.TextStyleWithFont(baseFont);
        t.Header = t.Parent.FontSize(20).FontColor(new PdfGrayColor(20));
        t.Footer = t.Footnote;
    });

    doc.Pages(page =>
    {
        page.Header().AlignCenter().Text("Header");

        page.Content().Text(t =>
        {
            t.Line("Title").Style(t => t.Title);
            t.Line("Heading 1").Style(t => t.Heading1);
            t.Line("Regular");
        });

        page.Footer().Height(20).AlignCenter().Text(t => t.CurrentPageNumber());
    });
});

With the Typography class, you do not need to use variables to keep text style references. You register necessary styles using the Document.Typography methods and later load them from the Typography object. Look how to use predefined and custom styles in the Typography sample.

Images

Like text and fonts, images are another fundamental part of PDF documents. The layout API allows you to add images like that:

PdfDocumentBuilder.Create().Generate("image.pdf", doc =>
{
    var imageFile = new FileInfo("image.jpg");
    Image image = doc.Image(imageFile);
    doc.Pages(page => page.Content().MaxWidth(200).Image(image));
});

Tables

The layout API allows you to generate tables. This C# sample shows how to add table to a PDF document:

PdfDocumentBuilder.Create().Generate("table.pdf", doc =>
{
    doc.Pages(page =>
    {
        page.Content().Table(t =>
        {
            t.Columns(c =>
            {
                c.ConstantColumn(200);
                c.RelativeColumn(1);
            });

            t.Header(h =>
            {
                h.Cell().Text("Product");
                h.Cell().Text("Features");
            });

            t.Cell().Text("Docotic.Pdf");
            t.Cell().Text("Extract text, PDF to images, compress PDF");
            t.Cell().Text("Docotic.Pdf.Layout");
            t.Cell().Text("Create PDF");
        });
    });
});

You can create tables of any complexity. This sample shows how to use cell borders, backgrounds, and spans.

PDF documents support internal links that allow you to generate bookmarks or table of contents. This basic C# sample shows how to add a link to a document section using the layout API:

PdfDocumentBuilder.Create().Generate("link.pdf", doc =>
{
    doc.Pages(page =>
    {
        page.Content().Column(c =>
        {
            const string SectionName = "Chapter 1";
            c.Item().SectionLink(SectionName).Text("Link");

            c.Item().PageBreak();

            c.Item().Section(SectionName).Text("Target");
        });
    });
});

You can also download and try the Add table of contents to PDF documents sample from GitHub.

Complex layouts

You can combine different layout components to generate complex PDF documents. Download and try the Generate PDF documents with complex layout sample from GitHub.

It is possible to extend the layout API. LayoutContainer.Component and LayoutContainer.Container methods allow you to re-use custom components. The Layout components sample shows how to implement a custom component using ILayoutComponent interface.

Conclusion

Docotic.Pdf library provides different means to create PDF documents in C# and VB.NET. You can generate PDF documents from scratch with or without using the layout add-on. Or you can create PDF from HTML using the HTML to PDF add-on.

Contact us if you have any questions about PDF generation.