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:
- Create an HTML template.
- Access the data and bind it with an HTML template.
- 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.
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.
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:
- How to Find Corrupted PDF Files in C# Easily
- Create Accessible PDF documents using C#
- HTML-to-PDF Conversion in C# – A Complete Guide
- Easy Ways to Redact PDFs Using C#
- 7 Ways to Compress PDF Files in C#, VB.NET
Comments (4)
//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);
In this code, For Template.Parse() which package do you have used because I am getting error like, The name ‘Template’ does not exist in current template
can you tell me ASAP?
Hi Vikas,
You have to use the following Nuget package to use the Template.Parse() code.
https://www.nuget.org/packages/Scriban/
Also, you can refer to the full working sample from the below GitHub link.
https://github.com/SyncfusionExamples/pdf-generation-from-html-template
Hello Praveenkumar,
I need your help. After applying your code to mine, i get a missing reference error here;
Invoice invoice = JsonConvert.DeserializeObject(File.ReadAllText(“~/Report_template/InvoiceData.json”));
All the “Invoice” are red underlined with this error message;
The type or namespace name ‘Invoice’ could not be found (are you missing a using directive or an assembly reference?)
I am using the following references;
using System.IO;
using PdfGeneration.Model;
using Scriban;
using Syncfusion.HtmlConverter;
using Syncfusion.Pdf;
using System.Linq;
using System.Text;
using System.Web;
using Newtonsoft.Json;
Although, PdfGeneration.Model; is also red underlined with the following error;
The type or namespace name ‘PdfGeneration’ could not be found (are you missing a using directive or an assembly reference?)
I’m not sure whether i need to download more references. When i hover on the invoice error and go to “show potential fixes”, VS is telling me to install Stripe.net from nuget.
Can you please help me out?
Hello,
I am getting a runtime error in this line
var templateData = new { invoice };
The error is => Scriban.Syntax.ScriptRuntimeException: (13,56) : error : Cannot get the member invoice.company_details.name for a null object.
I need assistance on how to handle this please.
Comments are closed.