How to create a PDF Report using ITextPDF libraries in your ASP.Net MVC Project?

The problem for most web application is printing.  Traditionally, the easiest way to have a printed report from a web page is to used a clean HTML page then let the browser print it out.  The problem of such print out is that you could not get a professional report formatted to an appropriate paper size, e.g., Letter, A4, etc.  The only reasonable solution that I could think off is to used an acceptable printable format like a PDF.

In this blog you will see how easy it is to build a report in an ASP.Net MVC application using a free IText PDF libraries.  By the way,  this project is still ASP.Net Webforms MVC 2, if you are already using Razor don’t just cut and paste the sample code, just get the jest and re-write it to suite to your project.

The first step is to add the libraries in your Visual Studio 2013 project by simply using the Manage NuGet Packages.

b3

Once the libraries are installed, just create a controller.  In my example, I named my controller SysReport because I want it to be a generic report controller for all my reporting needs.  The code contains one GET method and a bunch of private methods that returns a PDF MemoryStream created by ITextPDF.

using iTextSharp.text;
using iTextSharp.text.pdf;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Web;
using System.Web.Http;

namespace wfmis.Controllers
{
    public class SysReportController : ApiController
    {
        public HttpResponseMessage Get()
        {
            NameValueCollection nvc = HttpUtility.ParseQueryString(Request.RequestUri.Query);
            string Report = nvc["Report"].ToString();
            Int64 Id = Convert.ToInt64(nvc["Id"]);
            var response = new HttpResponseMessage(HttpStatusCode.OK);

            switch (Report)
            {
                case "PurchaseOrder":
                    response.Content = new StreamContent(this.PurchaseOrder(Id));
                    response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
                    break;
                case "PurchaseInvoice":
                    response.Content = new StreamContent(this.PurchaseInvoice(Id));
                    response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
                    break;
                case "Disbursement":
                    response.Content = new StreamContent(this.Disbursement(Id));
                    response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
                    break;
                case "SalesOrder":
                    response.Content = new StreamContent(this.SalesOrder(Id));
                    response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
                    break;
                case "SalesInvoice":
                    response.Content = new StreamContent(this.SalesInvoice(Id));
                    response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
                    break;
                case "Collection":
                    response.Content = new StreamContent(this.Collection(Id));
                    response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
                    break;
                case "JournalVoucher":
                    response.Content = new StreamContent(this.JournalVoucher(Id));
                    response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
                    break;
                case "StockIn":
                    response.Content = new StreamContent(this.StockIn(Id));
                    response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
                    break;
                case "StockOut":
                    response.Content = new StreamContent(this.StockOut(Id));
                    response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
                    break;
                case "StockTransfer":
                    response.Content = new StreamContent(this.StockTransfer(Id));
                    response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
                    break; 
            }

            return response;
        }
    }
}

The second part of the controller is the method that creates the report itself.  Noticed that in the above code I highlighted two lines, the first line, calls the method that creates the byte stream while the second line informs the controller what is the content type, those are the methods.  I cannot paste the entire code that contains all the methods because it will take a lot of typing space, what I can paste is just one sample method, PurchaseInvoice.

        private MemoryStream PurchaseInvoice(Int64 Id)
        {
            var doc = new Document(PageSize.LETTER, 50, 50, 25, 25);
            var stream = new MemoryStream();

            try
            {
                BaseFont BaseFontTimesRoman = BaseFont.CreateFont(BaseFont.TIMES_ROMAN, BaseFont.CP1252, false);
                Font TitleFont = new Font(BaseFontTimesRoman, 18, Font.BOLD);
                Font SubTitleFont = new Font(BaseFontTimesRoman, 14, Font.BOLD);
                Font TableHeaderFont = new Font(BaseFontTimesRoman, 10, Font.BOLD);
                Font BodyFont = new Font(BaseFontTimesRoman, 10, Font.NORMAL);
                Font EndingMessageFont = new Font(BaseFontTimesRoman, 10, Font.ITALIC);

                PdfWriter writer = PdfWriter.GetInstance(doc, stream);

                writer.PageEvent = new PDFHeaderFooter("Purchase Invoice");

                var PurchaseInvoices = from d in db.TrnPurchaseInvoices where d.Id == Id select d;

                doc.Open();

                var HeaderTable = new PdfPTable(2);
                HeaderTable.HorizontalAlignment = 0;
                HeaderTable.SpacingBefore = 20;
                HeaderTable.SpacingAfter = 10;
                HeaderTable.DefaultCell.Border = 0;
                HeaderTable.SetWidths(new int[] { 2, 6 });

                HeaderTable.AddCell(new Phrase("PI Number:", TableHeaderFont));
                HeaderTable.AddCell(new Phrase(PurchaseInvoices.First().PINumber, BodyFont));
                HeaderTable.AddCell(new Phrase("PI Date:", TableHeaderFont));
                HeaderTable.AddCell(new Phrase(PurchaseInvoices.First().PIDate.ToShortDateString(), BodyFont));
                HeaderTable.AddCell(new Phrase("Supplier:", TableHeaderFont));
                HeaderTable.AddCell(new Phrase(PurchaseInvoices.First().MstArticle.Article, BodyFont));
                HeaderTable.AddCell(new Phrase("Term:", TableHeaderFont));
                HeaderTable.AddCell(new Phrase(PurchaseInvoices.First().MstTerm.Term, BodyFont));
                HeaderTable.AddCell(new Phrase("Document Reference:", TableHeaderFont));
                HeaderTable.AddCell(new Phrase(PurchaseInvoices.First().DocumentReference, BodyFont));

                doc.Add(HeaderTable);

                var DetailTable = new PdfPTable(7);
                DetailTable.HorizontalAlignment = 0;
                DetailTable.SpacingAfter = 10;
                DetailTable.DefaultCell.Border = 0;
                DetailTable.SetWidths(new int[] { 2, 2, 6, 3, 3, 3, 3 });
                DetailTable.WidthPercentage = 100;
                DetailTable.DefaultCell.Border = Rectangle.BOX;

                DetailTable.AddCell(CreateCenterAlignedCell("Qty", TableHeaderFont, 1));
                DetailTable.AddCell(CreateCenterAlignedCell("Unit", TableHeaderFont, 1));
                DetailTable.AddCell(CreateCenterAlignedCell("Item", TableHeaderFont, 1));
                DetailTable.AddCell(CreateCenterAlignedCell("Particulars", TableHeaderFont, 1));
                DetailTable.AddCell(CreateCenterAlignedCell("Cost", TableHeaderFont, 1));
                DetailTable.AddCell(CreateCenterAlignedCell("Tax", TableHeaderFont, 1));
                DetailTable.AddCell(CreateCenterAlignedCell("Amount", TableHeaderFont, 1));

                decimal TotalAmount = 0;
                if (PurchaseInvoices.First().TrnPurchaseInvoiceLines.Any())
                {
                    foreach (var Line in PurchaseInvoices.First().TrnPurchaseInvoiceLines) 
                    {
                        DetailTable.AddCell(CreateRightAlignedCell(Line.Quantity.ToString("#,##0.#0"), BodyFont,1));
                        DetailTable.AddCell(new Phrase(Line.MstUnit.Unit, BodyFont));
                        DetailTable.AddCell(new Phrase(Line.MstArticle.Article, BodyFont));
                        DetailTable.AddCell(new Phrase(Line.Particulars, BodyFont));
                        DetailTable.AddCell(CreateRightAlignedCell(Line.Cost.ToString("#,##0.#0"), BodyFont,1));
                        DetailTable.AddCell(new Phrase(Line.MstTax.TaxCode, BodyFont));
                        DetailTable.AddCell(CreateRightAlignedCell(Line.Amount.ToString("#,##0.#0"), BodyFont,1));

                        TotalAmount = TotalAmount + Line.Amount;
                    }
                }

                DetailTable.AddCell(CreateCenterAlignedCell("TOTAL", TableHeaderFont, 6));
                DetailTable.AddCell(CreateRightAlignedCell(TotalAmount.ToString("#,##0.#0"), TableHeaderFont, 1));

                doc.Add(DetailTable);

                var SignatureTable = new PdfPTable(3);
                SignatureTable.HorizontalAlignment = 0;
                SignatureTable.SpacingBefore = 10;
                SignatureTable.SpacingAfter = 10;
                SignatureTable.SetWidths(new int[] { 6, 6, 6 });
                SignatureTable.WidthPercentage = 100;
                SignatureTable.DefaultCell.Border = Rectangle.BOX;

                SignatureTable.AddCell(CreateLeftAlignedCell("Prepared By:", TableHeaderFont, 1));
                SignatureTable.AddCell(CreateLeftAlignedCell("Checked By: ", TableHeaderFont, 1));
                SignatureTable.AddCell(CreateLeftAlignedCell("Approved By:", TableHeaderFont, 1));

                PdfPCell cell1 = new PdfPCell(new Phrase(PurchaseInvoices.First().MstUser.FullName, BodyFont)) { HorizontalAlignment = PdfPCell.ALIGN_CENTER, VerticalAlignment = PdfPCell.ALIGN_BOTTOM };
                PdfPCell cell2 = new PdfPCell(new Phrase(PurchaseInvoices.First().MstUser1.FullName, BodyFont)) { HorizontalAlignment = PdfPCell.ALIGN_CENTER, VerticalAlignment = PdfPCell.ALIGN_BOTTOM };
                PdfPCell cell3 = new PdfPCell(new Phrase(PurchaseInvoices.First().MstUser2.FullName, BodyFont)) { HorizontalAlignment = PdfPCell.ALIGN_CENTER, VerticalAlignment = PdfPCell.ALIGN_BOTTOM };

                cell1.FixedHeight = 50f;
                cell2.FixedHeight = 50f;
                cell3.FixedHeight = 50f;

                SignatureTable.AddCell(cell1);
                SignatureTable.AddCell(cell2);
                SignatureTable.AddCell(cell3);

                doc.Add(SignatureTable);

                doc.Close();
            }
            catch { }

            byte[] file = stream.ToArray();
            MemoryStream output = new MemoryStream();
            output.Write(file, 0, file.Length);
            output.Position = 0;

            return output;
        }

Now it may look gruesome at first, because it is 100% hardcore code to create a report, but once you start writing it down you will get a familiarity of the ITextPDF libraries, which is very powerful and customizable, the code will be clearer and understandable.  I hightlighted a single line above because this line is optional, it is just merely overloading the PdfPageEventHelper class to create a header and footer of the report.  I will discuss this soon in my future blogs.

In order also to fully understand the code, below is the sample actual output report created by the code.

b1

And the last step is to call the controller in your views, it turns out, it is very simple as shown in the sample Javascript code below.

function cmdPrint_onclick() 
   {
      if ($Id > 0) 
      {
         window.location.href = '/api/SysReport?Report=PurchaseInvoice?Id=' + $Id;
      }
}

That’s it.  Happy coding and if you find this blog helpful, you can make the donation by clicking the Paypal button below.


					
Advertisements
About

Software developer living in the Philippines.

Posted in ASP.NET
4 comments on “How to create a PDF Report using ITextPDF libraries in your ASP.Net MVC Project?
  1. Shafqat says:

    Where is the code for PDFHeaderFooter(“Purchase Invoice”); CreateXXXXAlignedCell.. functions/classes

    • Shafqat says:

      Please upload complete working project

    • hgminerva says:

      It is just a simple function

      private PdfPCell CreateRightAlignedCell(string text, Font font, int span) {
      PdfPCell cell = new PdfPCell(new Phrase(text, font)) { HorizontalAlignment = PdfPCell.ALIGN_RIGHT };
      cell.Colspan = span;
      return cell;
      }
      private PdfPCell CreateLeftAlignedCell(string text, Font font, int span)
      {
      PdfPCell cell = new PdfPCell(new Phrase(text, font)) { HorizontalAlignment = PdfPCell.ALIGN_LEFT };
      cell.Colspan = span;
      return cell;
      }
      private PdfPCell CreateCenterAlignedCell(string text, Font font, int span)
      {
      PdfPCell cell = new PdfPCell(new Phrase(text, font)) { HorizontalAlignment = PdfPCell.ALIGN_CENTER };
      cell.Colspan = span;
      return cell;
      }

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Author

Harold Glenn P. Minerva
Software Developer / Tech Enthusiast
Living in the Philippines

View Harold Glenn Minerva's profile on LinkedIn

Instagram

Software Engineer - Seasonal and Range Trading Software. Magenta Trader is a powerful stock market visualization software that increases your probability of trading success.

Software Architect and Founder - Easyfis.com is a multi-tenant cloud-based Software-as-a-Service (SaaS) business app that caters to micro, small and medium trading businesses.

CTO and Co-Founder - We give your company the leverage by providing innovative software solutions products such as Point-of-Sales (POS), Financial Information System (FMIS), Payroll and DTR (HRIS), and many more.

%d bloggers like this: