Friday 4 November 2016

Dynamic PDF with C sharp MVC and iTextSharp.

 Dynamic PDF creation using ASP.net MVC razor and   iTextSharp.


    Hey guys ,

   This is my first blog, so if you have any concerns please do inform me through comments.

   So in this session we can have a demo of generating dynamic PDF files using ASP.net MVC C# and iTextSharp which supports inline CSS styles.

IDE :- VS Express for web 2013

Utilities :-
Demo Scenario  :-  

This is a small part of  an Employee Management System where Payslip of employees should be generated in PDF format.

 
Walk Around :-

In order to give a complete example we can create an application from scratch. To avoid complexity  this session is been divided to a step by step guide.

step 1 :-  Create a new project.




step 2 :- Add additional plugins through nuget or package manage console.


  Here we need two plugins.

  •   itextsharp
  •   itextsharp,xmlworker
PM>  Install-Package iTextSharp

PM> Install-Package itextsharp.xmlworker






Step 3 :-  Add your desired Controller  >  Action  >  View > Model.

View ->


Step 4 :- Add J query code to bind click event to button with id "generate".


<script type="text/javascript">
    $("#generate").click(function () {

        window.location = "/PaymentVoucher/" + "GeneratePDF";

    });

</script>



Here its given to redirect from our current page to the method 'GeneratePDF' where the code for PDF generation is been coded.

Step 5 :- Get the data that to be rendered to PDF from your database. In this eg a static data have been created for the demo purpose.

Model for Payslip ->


  public class Payslip
    {
        public int EmployeeID { get; set; }
        public string Employer { get; set; }
        public string Employee { get; set; }
        public string DateOfPayment { get; set; }
        public string ModeOfPayment { get; set; }
        public string OTHours { get; set; }
        public string OTTotalPay { get; set; }
        public string SalaryPeriod { get; set; }
        public string SalaryPeriodFrom { get; set; }
        public string SalaryPeriodTo { get; set; }
        public List<Term> AllowanceTermList { get; set; }
        public List<Term> DeductionTermList { get; set; }
        public string TotalAllowance { get; set; }
        public string TotalDeductions { get; set; }
        public int GenerateSatus { get; set; }
        public string NetPay { get; set; }
    }

    public class Term
    {
        public int EmployeeID { get; set; }
        public string EDType { get; set; }
        public string TermName { get; set; }
        public string Amount { get; set; }
        public string TermType { get; set; }
    }

}

Static data ->



 public List<Payslip> GetStaticData()
        {
            List<Payslip> payslipList = new List<Payslip>();
            List<Term> allowanceTermList1 = new List<Term>();
            List<Term> deductionTermList1 = new List<Term>();
            List<Term> allowanceTermList2 = new List<Term>();
            List<Term> deductionTermList2 = new List<Term>();

            allowanceTermList1.Add(new Term { TermName = "Basic Pay", Amount = "$800" });
            allowanceTermList1.Add(new Term { TermName = "Travel Allowance", Amount = "$100" });
            allowanceTermList1.Add(new Term { TermName = "Dearness Allowance", Amount = "$200" });
            allowanceTermList2.Add(new Term { TermName = "Basic Pay", Amount = "$900" });
            allowanceTermList2.Add(new Term { TermName = "Travel Allowance", Amount = "$100" });
            allowanceTermList2.Add(new Term { TermName = "Dearness Allowance", Amount = "$200" });
            deductionTermList1.Add(new Term { TermName = "PF", Amount = "$100" });
            deductionTermList1.Add(new Term { TermName = "LOP", Amount = "$100" });
            deductionTermList2.Add(new Term { TermName = "PF", Amount = "$100" });
            deductionTermList2.Add(new Term { TermName = "LOP", Amount = "$100" });
            payslipList.Add(new Payslip
            {
                AllowanceTermList = allowanceTermList1,
                DeductionTermList = deductionTermList1,
                ModeOfPayment = "",
                OTHours = "6",
                OTTotalPay = "$600",
                Employee = "Jennifer",
                Employer = "ABC Exports pvt ltd",
                DateOfPayment = string.Format("{0:dd MMM yyyy}", DateTime.Now.AddMonths(-5)),
                SalaryPeriodFrom = string.Format("{0:dd MMM yyyy}", DateTime.Now.AddMonths(-5).AddDays(1)),
                SalaryPeriodTo = string.Format("{0:dd MMM yyyy}", DateTime.Now.AddMonths(-5).AddDays(30)),
                TotalAllowance = "$11000",
                TotalDeductions = "$300",
                NetPay = "$1500"
            });
            payslipList.Add(new Payslip
            {
                AllowanceTermList = allowanceTermList2,
                DeductionTermList = deductionTermList2,
                ModeOfPayment = "",
                OTHours = "6",
                OTTotalPay = "$600",
                Employee = "Jennifer",
                Employer = "ABC Exports pvt ltd",
                DateOfPayment = string.Format("{0:dd MMM yyyy}", DateTime.Now.AddMonths(-4)),
                SalaryPeriodFrom = string.Format("{0:dd MMM yyyy}", DateTime.Now.AddMonths(-4).AddDays(1)),
                SalaryPeriodTo = string.Format("{0:dd MMM yyyy}", DateTime.Now.AddMonths(-4).AddDays(1)),
                TotalAllowance = "$12000",
                TotalDeductions = "$300",
                NetPay = "$1500"
            });
            return payslipList;
        }




Step 6 :-  Render PDF from the retrieved data.


 public ActionResult GeneratePDF()
        {

            List<Payslip> payslipList = GetStaticData();
            .....


  In order to continue we need to create a View which should be binded  with the Model  List<Payslip> 

Note :- As its already mentioned this method only supports inline styles.

  Now we will convert this View to string.
           .....
            var viewString = RenderRazorViewToString("PaySlipPdf", payslipList);

Create a byte array that will eventually hold our final PDF.

           .....
          Byte[] bytes;

Boilerplate iTextSharp setup here
Create a stream that we can write to, in this case a MemoryStream.

             .....
            using (var ms = new MemoryStream())
            {

             Create an iTextSharp Document which is an abstraction of a PDF but **NOT** a PDF.

                 .....
                using (var doc = new Document())
                {

                    Create a writer that's bound to our PDF abstraction and our stream.

                      .....
                    using (var writer = PdfWriter.GetInstance(doc, ms))
                    {

                        Open the document for writing.

                        .....
                        doc.Open();

                        XMLWorker also reads from a TextReader and not directly from a string.

                          .....
                        using (var srHtml = new StringReader(viewString))
                        {

                            Parse the HTML.

                             .....
                            iTextSharp.tool.xml.XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, srHtml);
                        }

                        doc.Close();
                    }
                }

                After all of the PDF "stuff" above is done and closed but **before** we
                close the MemoryStream, grab all of the active bytes from the stream.

                bytes = ms.ToArray();

            }


 Converts byte array to stream using MemoryStream.

 Stream stream = new MemoryStream(bytes);

Return it as PDF file type.

 return File(stream, "application/pdf", "PDFfile.pdf");
}


So after doing all this stuff you will be returned to your Generate page with the save or open PDF dialogue box



PDF output should be like this:-






And with this our session has came to an end. If you guys have any doubt please do comment below. 

Please don't be hesitated to download the entire project from the link mentioned below.






No comments:

Post a Comment