Introduction
This tip shows how to export HTML to PDF with Bookmark and TOC using iTextSharp. Technology includes ASP.NET MVC, iTextSharp 4.1.6 (LGPL/MPL).
Prepare Your HTML Content
Create new view has name PDFContent.cshtml with your content. Here is a sample:
<h2>Introduction</h2>
<p>This article shows how to create a load more button to your Kendo Grid
without using default paging control. Technology includes ASP.NET MVC,
jQuery and Kendo Grid Controls. I also used SQL Server Database Northwind for this sample.</p>
<br/>
<h2>Background</h2>
<p>With Kendo Grid you can easily configure the grid to display data and perform sorting,
paging and grouping operations via its built-in settings. Now, I will show you how to add a
load more button without using paging control. This article will apply for
both server and client paging of Kendo Grid.</p>
<br />
<h2>Setting up Environment</h2>
<p>Please follow steps instruction
<a href="http://docs.telerik.com/kendo-ui/aspnet-mvc/introduction">here
</a>to setup environment.</p>
...
Using the Code
Step 1 - Add iTextSharp References and Create Your New Action for Controller
This action will export PDF on your Controller, as follows:
using iTextSharp;
using iTextSharp.text;
using iTextSharp.text.html;
using iTextSharp.text.html.simpleparser;
using iTextSharp.text.pdf;
public ActionResult Index()
{
string htmlContent = RenderRazorViewToString("~/Views/Shared/PDFContent.cshtml");
return File(GenerateHtmlToPDFDocument(htmlContent), "application/pdf");
}
With the PDFContent.cshtml we've just created above.
Step 2 - Render Razor View to String
We need to create a function RenderRazorViewToString
to get the content in PDFContent.cshtml, as follows:
public string RenderRazorViewToString(string viewName)
{
using (var sw = new StringWriter())
{
var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
viewResult.View.Render(viewContext, sw);
return sw.GetStringBuilder().ToString();
}
}
Step 3 - Create Bookmark From Your HTML Content
This function will split all H2
tags in your HTML content and create section for them.
public Chapter CreateChapterContent(string html)
{
iTextSharp.text.Font bookmarkFont = iTextSharp.text.FontFactory.GetFont
(iTextSharp.text.FontFactory.HELVETICA, 16, iTextSharp.text.Font.NORMAL, new Color(255, 153, 0));
Chapter chapter = new Chapter(new Paragraph(""), 0);
chapter.NumberDepth = 0;
StyleSheet styles = new StyleSheet();
styles.LoadTagStyle("h2", HtmlTags.HORIZONTALALIGN, "center");
styles.LoadTagStyle("h2", HtmlTags.COLOR, "#F90");
styles.LoadTagStyle("pre", "size", "10pt");
string pattern = @"<\s*h2[^>]*>(.*?)<\s*/h2\s*>";
string[] result = Regex.Split(html, pattern);
int sectionIndex = 0;
foreach (var item in result)
{
if (string.IsNullOrEmpty(item)) continue;
if (sectionIndex % 2 == 0)
{
chapter.AddSection(20f, new Paragraph(item, bookmarkFont), 0);
}
else
{
foreach (IElement element in HTMLWorker.ParseToList(new StringReader(item), styles))
{
chapter.Add(element);
}
}
sectionIndex++;
}
chapter.BookmarkTitle = "Demo for Load More Button in Kendo UI Grid";
return chapter;
}
Step 4 - Generate PDF Document
First, we need to generate chapter content from Step 3 to PDF Document.
public byte[] GenerateHtmlToPDFDocument(string html)
{
MemoryStream workStream = new MemoryStream();
Document pdfDoc = new Document(PageSize.A4);
PdfWriter.GetInstance(pdfDoc, workStream).CloseStream = false;
HTMLWorker parser = new HTMLWorker(pdfDoc);
Chapter chapter = CreateChapterContent(html);
pdfDoc.Open();
pdfDoc.Add(chapter);
pdfDoc.Close();
byte[] byteInfo = workStream.ToArray();
workStream.Write(byteInfo, 0, byteInfo.Length);
workStream.Position = 0;
return GeneratePDFTOCContent(byteInfo, html);
}
And then, we will generate TOC for your PDF, as follows:
public byte[] GeneratePDFTOCContent(byte[] content, string html)
{
var reader = new PdfReader(content);
StringBuilder sb = new StringBuilder();
sb.Append("<h2><strong style='text-align:center'>
Demo for Load More Button in Kendo UI Grid</strong></h2><br>");
sb.Append("<table>");
sb.Append(string.Format("<tr><td width='80%'><strong>
{0}</strong></td><td align='right' width='10%'>
<strong>{1}</strong></td></tr>", "Section",
"Page"));
using (MemoryStream ms = new MemoryStream())
{
SimpleBookmark.ExportToXML(SimpleBookmark.GetBookmark(reader), ms, "UTF-8", false);
ms.Position = 0;
using (XmlReader xr = XmlReader.Create(ms))
{
xr.MoveToContent();
string page = null;
string text = null;
string format = @"<tr><td width='80%'>{0}</td>
<td align='right' width='10%'>{1}</td></tr>";
Regex re = new Regex(@"^\d+");
while (xr.Read())
{
if (xr.NodeType == XmlNodeType.Element &&
xr.Name == "Title" && xr.IsStartElement())
{
page = re.Match(xr.GetAttribute("Page")).Captures[0].Value;
xr.Read();
if (xr.NodeType == XmlNodeType.Text)
{
text = xr.Value.Trim();
int pageSection = int.Parse(page) + 1;
sb.Append(String.Format(format, text, pageSection.ToString()));
}
}
}
}
}
sb.Append("</table>");
MemoryStream workStream = new MemoryStream();
var document = new Document(reader.GetPageSizeWithRotation(1));
var writer = PdfWriter.GetInstance(document, workStream);
writer.CloseStream = false;
document.Open();
document.NewPage();
StyleSheet styles = new StyleSheet();
styles.LoadTagStyle("h2", HtmlTags.HORIZONTALALIGN, "center");
styles.LoadTagStyle("h2", HtmlTags.COLOR, "#F90");
foreach (IElement element in HTMLWorker.ParseToList(new StringReader(sb.ToString()), styles))
{
document.Add(element);
}
Chapter chapter = CreateChapterContent(html);
document.Add(chapter);
document.Close();
writer.Close();
byte[] byteInfo = workStream.ToArray();
workStream.Write(byteInfo, 0, byteInfo.Length);
workStream.Position = 0;
return byteInfo;
}
References
- iTextSharp - Links and Bookmarks
- Creating HTML Table of Contents from PDF Bookmarks
- Render a razor view to string
- Demo for Load More Button in Kendo UI Grid
History
- 24th April, 2015 - Initial version