File Formats

Generate Dynamic PDF Reports from an HTML Template Using C#

Generating PDF documents from the scratch is always a difficult process and has the following disadvantages:

  • It is time-consuming.
  • It is challenging to design a complex PDF.
  • It is prone to errors.

It is always advisable to generate PDF documents from well-designed HTML templates. In this blog post, we will see how to generate PDF reports from HTML templates using Syncfusion’s HTML-to-PDF converter in C#.

The HTML-to-PDF converter supports all modern features such as HTML5, CSS3, SVG, and web fonts. So, you can easily style your PDF reports by updating the CSS file with your images and fonts in C#.

To demonstrate this, we are going to generate a PDF invoice from an HTML template using C# with the following steps:

  1. Create an HTML template.
  2. Access the data and bind it with an HTML template.
  3. Convert the HTML string to PDF.

Syncfusion .NET HTML-to-PDF converter:

  • Convert any HTML file to PDF.
  • Preserve graphics, text, forms, and more.
  • Encrypt the PDF with a password.

Create an HTML template

An HTML template contains placeholders with {{mustache}} syntax. It is used to bind the actual data to the HTML template. For this example, we’ll use the Scriban scripting language to create the placeholders. It’s a lightweight scripting language and engine for .NET.

Note: To learn more about the Scriban scripting language, refer to the documentation.

The following code example shows the data model for the invoice.

public class Invoice
{
  public string InvoiceNumber { get; set; }
  public string IssueDate { get; set; }
  public string DueDate { get; set; }

  public UserDetails CompanyDetails { get; set; }
  public UserDetails CustomerDetails { get; set; }

  public List<Item> Items { get; set; }

  public decimal SubTotal
  {
    get
    {
      return Items.Sum(x => x.Price * x.Quantity);
    }
  }

  public float Tax
  {
    get
    {
       return (float)SubTotal * (25f / 100f);
    }
  }

  public float GrandTotal
  {
    get
    {
      return (float)SubTotal + Tax;
    }
  }
}

Based on this model, we design the template as follows. By default, the properties and methods of .NET objects are automatically exposed with lowercase and _ names. This means that a property like Invoice.CompanyDetails.Name will be exposed as invoice.company_details.name. This is the default convention.

<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Invoice</title>
    <link rel="stylesheet" href="style.css" media="all" />
  </head>
  <body>
    <header class="clearfix">
      <div id="logo">
        <img src="logo.png">
      </div>
      <div id="company">
        <h2 class="name">{{invoice.company_details.name}}</h2>
        <div>{{invoice.company_details.address}}</div>
        <div>{{invoice.company_details.phone}}</div>
        <div>{{invoice.company_details.email}}</div>
      </div>
      </div>
    </header>
    <main>
      <div id="details" class="clearfix">
        <div id="client">
          <div class="to">INVOICE TO:</div>
          <h2 class="name">{{invoice.customer_details.name}}</h2>
          <div class="address">{{invoice.customer_details.address}}</div>
          <div class="email">{{invoice.customer_details.email}}</div>
        </div>
        <div id="invoice">
          <h1>{{invoice.invoice_number}}</h1>
          <div class="date">Date of Invoice: {{invoice.issue_date}}</div>
          <div class="date">Due Date: {{invoice.due_date}}</div>
        </div>
      </div>
      <table border="0" cellspacing="0" cellpadding="0">
        <thead>
          <tr>
            <th class="no">#</th>
            <th class="desc">DESCRIPTION</th>
            <th class="unit">UNIT PRICE</th>
            <th class="qty">QUANTITY</th>
            <th class="total">TOTAL</th>
          </tr>
        </thead>
        <tbody id="invoiceItems">
    {{- index = 1 -}}
    {{ for item in invoice.items }}
          <tr>
            <td class="no">{{index}}</td>
            <td class="desc"><h3>{{item.name}}</h3>{{item.description}}</td>
            <td class="unit">${{item.price}}</td>
            <td class="qty">{{item.quantity}}</td>
            <td class="total">${{item.total_price}}</td>
          </tr>
    {{index = index + 1}}
    {{end}}
        </tbody>
        <tfoot>
          <tr>
            <td colspan="2"></td>
            <td colspan="2">SUBTOTAL</td>
            <td>${{invoice.sub_total}}</td>
          </tr>
          <tr>
            <td colspan="2"></td>
            <td colspan="2">TAX 25%</td>
            <td>${{invoice.tax}}</td>
          </tr>
          <tr>
            <td colspan="2"></td>
            <td colspan="2">GRAND TOTAL</td>
            <td>${{invoice.grand_total}}</td>
          </tr>
        </tfoot>
      </table>
      <div id="thanks">Thank you!</div>
      <div id="notices">
        <div>NOTICE:</div>
        <div class="notice">A finance charge of 1.5% will be made on unpaid balances after 30 days.</div>
      </div>
    </main>
  </body>
</html>

You can get this HTML template with CSS and fonts from this GitHub repository.

The following screenshot shows the output of the HTML template with styled CSS.

Invoice HTML template

Everything you need to know about the comprehensive features of Syncfusion’s robust HTML-to-PDF converter.

Access the data and bind it with the HTML template

To simplify this article, we have used a custom JSON file to store and retrieve the data. The following code snippet is used to create the invoice model.

Invoice invoice= JsonConvert.DeserializeObject<Invoice>(File.ReadAllText("../../../InvoiceData.json"));

Now, we use Scriban to bind the data from the model to the HTML template, as explained in the following code example.

//Load html HTML template.
var invoiceTemplate = File.ReadAllText("../../../Template/index.html");
var template = Template.Parse(invoiceTemplate);
var templateData = new { invoice };
//Fill template with real invoice data.
var pageContent = template.Render(templateData);

Check out our demo of converting URLs to PDFs with custom features.

Convert HTML string to PDF

The last step is to generate the invoice PDF from the bound HTML created in the previous section.

We use the HtmlToPdfConverter to convert the HTML string to a PDF document. Refer to the following code example.

//Initialize HTML to PDF converter with Blink rendering engine.
HtmlToPdfConverter htmlConverter = new HtmlToPdfConverter(HtmlRenderingEngine.Blink);

//Convert HTML string to PDF. 
PdfDocument document = htmlConverter.Convert(pageContent , Path.GetFullPath("Template"));

FileStream fs = new FileStream("Output.pdf", FileMode.OpenOrCreate, FileAccess.ReadWrite);

//Save and close the PDF document.
document.Save(fs);

document.Close(true);

After the conversion, you will get a PDF document like in the following screenshot.

Invoice PDF document

GitHub samples

For better understanding, we have committed the source for this project in the PDF generation from HTML template GitHub repository.

Join thousands of developers who rely on Syncfusion for their PDF needs. Experience the difference today!

Conclusion

In this blog post, we have learned how to generate PDF reports from an HTML template using Syncfusion’s C# HTML-to-PDF converter.

Take a moment to look at the documentation, where you will find other options and features, all with accompanying code samples.

Please let us know in the comments below if you have any questions about these features. You can also contact us through our support forum, support portal or feedback portal. We are happy to assist you!

Related blogs

If you liked this article, we think you would also like the following articles about PDF Library:

Praveenkumar

Praveenkumar is the Product Manager for PDF at Syncfusion. He has been a .NET developer since 2012. He is specialized in PDF file format and .Net technologies.