How to Programmatically Generate PDF Documents in .NET C#
Tags: webdev, devops, pdf, tutorial
Published: 2023-07-17 20:45:12

---
canonical_url: https://developer.mescius.com/blogs/how-to-programmatically-generate-pdf-documents-in-net-c-sharp
description: Learn how to programmatically generate PDF Documents in .NET C#.
---
This blog will help you get started with [GrapeCity Documents for PDF](https://developer.mescius.com/document-solutions/dot-net-pdf-api) (or GcPdf). We will walk you through a series of steps on how to use GcPdf text handling and image features to create a real-time PDF by the end of the blog.

1.  [Installation](#step1)
2.  [Setting up your project](#step2)
3.  [Create a new PDF Document](#step3)
4.  [Add Titles for the PDF Document](#step4)
5.  [Add Paragraph](#step5)
6.  [Add Widow and Orphan control](#step6)
7.  [Render the text and images](#step7)
8.  [Save to PDF](#step8)

Let's get started with these steps.

## <a id="step1"></a>Step 1: Installation

You can also watch the videos in "[Get Started with Documents for PDF in Windows, Mac, and Linux](https://developer.mescius.com/blogs/get-started-with-document-api-pdf-windows-mac-linux)" to install Documents for PDF, set up your project, and create a document.

### Prerequisites

GcPdf can be used in any application that targets .NET Standard 2.0 (including .NET Core, .NET Framework, Mono, and Xamarin).

1.  Install .NET Core.
2.  Create a .NET Core Console Application in Visual Studio or use the dotnet CLI (command line interface.)

```
    dotnet new console
```

### Add GcPdf package

You can install the GcPdf NuGet package using Visual Studio or the dotnet CLI.

### Install using Visual Studio

1.  Right-click your project file or Resources (Dependencies in VS17), and click "Manage NuGet Packages."
2.  On the Browse tab at the top right, set the Package source to.
3.  In the Search box, type GrapeCity.Documents.
4.  Choose GrapeCity.Documents.Pdf and Install.

### Install using dotnet CLI

1.  Open a cmd window under your project folder.
2.  Execute this command:

```
        dotnet add package GrapeCity.Documents.Pdf​
```

## <a id="step2"></a>Step 2: Set up your project

### Add namespaces

1.  Open the Program.cs file from your project folder.
2.  Paste these namespaces under the existing using directives.

```
    using GrapeCity.Documents.Pdf;
    using GrapeCity.Documents.Text;
```

## <a id="step3"></a>Step 3: Create a new PDF document

In the Program.cs file's Main method, paste these two lines of code between the braces. Create a new document by calling GcPdfDocument class. Then add a new page to the document (GcPdfDocument does not have a page by default) and get the new page's Graphics object in order to draw elements on the page.

```
    GcPdfDocument doc = new GcPdfDocument();
    GcPdfGraphics g = doc.NewPage().Graphics;
```

## <a id="step4"></a>Step 4: Add titles for the PDF document

### Use the TextLayout class to add text

The TextLayout class can be used to add text and one or more paragraphs to your PDFs. You can set individual formatting of text fragments using different fonts, font styles, and colors. Refer to the [Documents for PDF Documentation](https://developer.mescius.com/document-solutions/dot-net-pdf-api/docs/online/overview.html) to read more about text features offered by GcPdf under the '[Text](https://developer.mescius.com/document-solutions/dot-net-pdf-api/docs/online/Text.html)' section.

To add titles to the PDF, create an instance of TextLayout class, set its size and margins, font, and font size. Note that you can reference a font from a .ttf file. You can get this font from the sample [here](https://developer.mescius.com/document-solutions/dot-net-pdf-api/demos/use-cases/wetlands/pdf-cs).

```
    TextLayout tl = new TextLayout(72)
    {
          MaxWidth = doc.PageSize.Width,
          MaxHeight = doc.PageSize.Height,
          MarginLeft = 72,
          MarginRight = 72,
          MarginTop = 72,
          MarginBottom = 72,
    };
    tl.DefaultFormat.Font = Font.FromFile(Path.Combine("Resources", "Fonts", "segoeui.ttf"));
    tl.DefaultFormat.FontSize = 11;
```

Then add two captions: one main caption on the document and the other a sub-caption. So you use two font settings on the two captions, but both are appended in the same TextLayout.

Finally, draw the text layout on the page using the graphics object.

Notice that we draw the TextLayout at PointF.Empty (0,0), i.e., at the top left corner of the page (in GcPdf, this is the coordinates' origin). Because we specified margins and page size on the TextLayout object itself, it will position the text correctly on the page.

```
    // Color for the title:
    var colorBlue = Color.FromArgb(0x3B, 0x5C, 0xAA);
    // Color for the highlights:
    var colorRed = Color.Red;
    // The text layout used to render text:
    tl.TextAlignment = TextAlignment.Center;
    tl.Append("Introduction\n", new TextFormat() { FontSize = 16, ForeColor = colorBlue });
    tl.Append("The Importance of Wetlands", new TextFormat() { FontSize = 13, ForeColor = colorBlue });
    tl.PerformLayout(true);
    g.DrawTextLayout(tl, PointF.Empty);
    At the end of this step, you can move below the caption, to start adding the first paragraph -

    // Move below the caption for the first para:
    tl.MarginTop = tl.ContentHeight + 72 * 2;
    tl.Clear();
    tl.TextAlignment = TextAlignment.Leading;
    tl.ParagraphSpacing = 12;
```

## <a id="step5"></a>Step 5: Add a paragraph

### Initialize the paragraph text

You can initialize the text (or paragraphs) you want to add to the PDF Document. For the brevity of this blog, the entire text is not included. View the text used for this PDF [here](https://developer.mescius.com/document-solutions/dot-net-pdf-api/demos/use-cases/wetlands/code-cs), initialized at the bottom of the program.

```
     string[] _paras = new string[]
     {"<Document text>"};
```

### Add a function to add paragraphs to the text layout

To add paragraphs, we'll add this function to the Main method. This function picks paragraphs from the **_paras** string array initialized above. In the paragraphs, some text needs to be highlighted in red. It identifies that text with the <red></red> tags. (In this example, for brevity, our "markup engine" only recognizes one tag and does not differentiate between opening and closing tags.)

```
    void addPara(string para)
    {
        // We implement a primitive markup to highlight some fragments in red:
        var txt = para.Split(new string[] { "<red>", "</red>" }, StringSplitOptions.None);
        for (int i = 0; i < txt.Length; ++i)
        {
            if (i % 2 == 0)
              tl.Append(txt[i]);
            else
              tl.Append(txt[i], new TextFormat(tl.DefaultFormat) { ForeColor = colorRed });
        }
        tl.AppendLine();
    }
```

### Render the first letter of the document with a larger font size

We can make the very first letter of the first paragraph bigger, but the paragraph text should be displayed with no first-line indent, so render it separately from the rest of the text. (TextLayout may contain text with different text formatting, but all paragraphs in it must have the same paragraph formatting, such as first-line indent.)

```
    tl.Append(_paras[0].Substring(0, 1), new TextFormat(tl.DefaultFormat) { FontSize = 22 });

Then, add the first paragraph and draw it on the page:

    addPara(_paras[0].Substring(1));
    tl.PerformLayout(true);
    g.DrawTextLayout(tl, PointF.Empty);
```

### Add other paragraphs

Set the TextLayout settings that would apply to all paragraphs. We offset the top margin of the rest of the text to take into account the first paragraph's height:

```
    tl.MarginTop = tl.ContentRectangle.Bottom;
    tl.Clear();
    tl.FirstLineIndent = 36;
```

Declare an object to hold images to add them in between the paragraphs:

```
    List<InlineObject> images = new List<InlineObject>();
```

Add the remaining paragraphs and image as an inline object:

```
    foreach (var para in _paras.Skip(1))
    {
        // Paragraphs starting with '::' indicate images to be rendered across the page width:
        if (para.StartsWith("::"))
        {
            var img = Image.FromFile(Path.Combine("Resources", "ImagesBis", para.Substring(2)));
            var w = tl.MaxWidth.Value - tl.MarginLeft - tl.MarginRight;
            var h = (float)img.Height / (float)img.Width * w;
            tl.AppendInlineObject(img, w, h);
            tl.AppendLine();
        }
        else
        {
             addPara(para);
        }
    }
    // Layout the paragraphs:
    tl.PerformLayout(true);
```

## <a id="step6"></a>Step 6: Add widow and orphan control

To render a long TextLayout that spans multiple pages, it must be split into chunks using the Split() method (or one of its variants). The TextSplitOptions class controls how the split is done.

You can set the TextSplitOptions to set widow and orphan control on the document. You can set the minimum number of lines you want to display in the first paragraph on the page and in the last paragraph.

```
    var tso = new TextSplitOptions(tl)
    {
        RestMarginTop = 72,
        MinLinesInFirstParagraph = 2,
        MinLinesInLastParagraph = 2,
    };
```

## <a id="step7"></a>Step 7: Render the text and images

Finally, using all the settings and steps above, split and render the text and images in a loop:

```
    // Image alignment used to render the pictures:
    var ia = new ImageAlign(ImageAlignHorz.Left, ImageAlignVert.Top, true, true, true, false, false) { BestFit = true };
    // In a loop, split and render the text:
    while (true)
    {
            var splitResult = tl.Split(tso, out TextLayout rest);
              g = doc.Pages.Last.Graphics;
            doc.Pages.Last.Graphics.DrawTextLayout(tl, PointF.Empty);
            // Render all images that occurred on this page:
            foreach (var io in tl.InlineObjects)
            doc.Pages.Last.Graphics.DrawImage((Image)io.Object, io.ObjectRect.ToRectangleF(), null, ia);
            // Break unless there is more to render:
            if (splitResult != SplitResult.Split)
              break;
            // Assign the remaining text to the 'main' TextLayout, add a new page and continue:
            tl = rest;
            doc.Pages.Add();
    }
```

## <a id="step8"></a>Step 8: Save to PDF

Finally, save the document to PDF:

```
    doc.Save(stream);
```

For the context of this sample, we have saved the document to stream. You can also save the document directly to a file:

```
    doc.Save("The Importance Of WetLands.pdf");
```

Here's the final product:

![Generate PDF C#](https://files.grapecity.com/gc-website-media/l0en0ico/wetlands.png?width=387.73747841105353&height=500)

You can find the sample implementing the above steps and observe the creation of a PDF [here](https://developer.mescius.com/document-solutions/dot-net-pdf-api/demos/use-cases/wetlands/pdf-cs).

We hope you enjoyed knowing the specifics of GcPdf. There is a lot more to explore with GcPdf. Refer to [demos](https://developer.mescius.com/document-solutions/dot-net-pdf-api/demos/) and [documentation](https://developer.mescius.com/document-solutions/dot-net-pdf-api/docs/online/overview.html) for more information. Thanks!