DEV Community

Guillermo Contreras
Guillermo Contreras

Posted on

How to generate a PDF report in .NET with zero dependencies

Generating a PDF invoice or report in .NET usually means a heavy dependency. Here's
how to do it with Matios.Pdf — a PDF engine that writes
the format (ISO 32000) itself, on the BCL alone. Zero dependencies, MIT.

Install

dotnet add package Matios.Pdf
Enter fullscreen mode Exit fullscreen mode

A report with a header, footer and a paginating table

The high-level PdfFlow stacks blocks and paginates on its own — repeating the
header/footer and the table's header row across pages:

using Matios.Pdf;

using var doc = new PdfDocument();
var flow = new PdfFlow(doc, PdfPageSize.A4, margin: 56);

flow.Header(40, a => a.Graphics.DrawString("Report", PdfFont.HelveticaBold, 13, a.X, a.Y + 14));
flow.Footer(28, a => a.Graphics.DrawString(
    $"Page {a.PageNumber} of {a.TotalPages}", PdfFont.Helvetica, 9, a.X + a.Width, a.Y + 14, PdfTextAlign.Right));

flow.Paragraph("A justified paragraph that wraps to the column width and paginates "
    + "on its own.", PdfFont.Helvetica, 12, leading: 16, align: PdfTextAlign.Justify, spacingAfter: 10);

flow.Table(t =>
{
    t.ProportionalColumns(6, 1, 2, 2);
    t.Align(PdfTextAlign.Left, PdfTextAlign.Right, PdfTextAlign.Right, PdfTextAlign.Right);
    t.HeaderRow("Description", "Qty", "Unit", "Total");
    for (int i = 1; i <= 40; i++)                       // enough rows to span pages
        t.Row($"Line item {i}", "1", "12.50", (i * 12.5).ToString("F2"));
});

flow.Save("report.pdf");
Enter fullscreen mode Exit fullscreen mode

Need pixel control instead? Drop to doc.Pages.Add(size).Graphics and draw text,
lines, rectangles, curves and images directly.

Full Unicode, embedded and subsetted

Embed a TrueType font and it's subsetted to just the glyphs you used — a ~1 MB
Arial becomes ~17 KB in the file, self-contained:

var font = PdfFont.FromFile(@"C:\Windows\Fonts\arial.ttf");
g.DrawString("Canción · €50 · ñandú · Ελληνικά · Русский", font, 14, 72, 160);
Enter fullscreen mode Exit fullscreen mode

Read and encrypt too

using var doc = PdfDocument.Load("in.pdf");        // parse an existing PDF
int pages = doc.Pages.Count;

using var secured = new PdfDocument();
secured.Encrypt("pass");                           // AES-256
secured.Pages.Add(PdfPageSize.A4).Graphics
    .DrawString("Confidential", PdfFont.HelveticaBold, 18, 72, 100);
secured.Save("secured.pdf");
Enter fullscreen mode Exit fullscreen mode

Every feature is verified by opening the output in real readers (pypdf, PIL,
FreeType), not just unit tests.

Docs, examples and benchmarks → pdf.matios.cl. Part of
a family of zero-dependency, MIT packages for .NET — matios.cl.

If you try it, I'd love your feedback — issues and stars welcome. 🙌

Top comments (0)