Search This Blog

2009-04-14

Generating PDF from .NET

How to generate pdf from asp.net,how to generate pdf from .NET,free pdf generator from .NET
1. Introduction

1.1 Background

Generation of PDF reports is a feature which is requested in most of the applications. This technical document introduces a component called iText, which is an open source DLL written in C# for .NET applications to generate PDF documents dynamically. The main advantage of using this component is - the dependency and complexity using other Third party tools like Crystal Reports™ for generation of PDF can be eliminated.

1.2 Usage

We can use this concept and code in both Windows and Web based applications to generate PDF documents.

The iText component and presented code has two usages
i. a static formatted PDF document can be generated and saved to a File location (OR)
ii. a formatted PDF document containing data from a database (Oracle/SQL) can be generated and saved to a File location



2. Approach

The iText.dll component can be downloaded from the following web site - http://sourceforge.net/project/platformdownload.php?group_id=72954

After downloading the iText.dll, add the DLL as a reference in your web or Windows .NET application and follow the steps mentioned below to create the sample PDF document.

Please Note - the Highlighted Items denote the user defined sections.
Please change the code accordingly as per your application requirements.

2.1 Sample Code

The following example shows the PDF generation for a web application.
The same code can be used in a Windows application as well.

1. Create a sample website from the .NET IDE

2. Create a page e.g. PdfReport.aspx, and then add the iText.dll as a reference to this application.
Include the following namespaces

using System.IO;
using System.Text;
using iTextSharp.text;
using iTextSharp.text.html.simpleparser;
using iTextSharp.text.pdf;

3. Create a File Folder (on your local machine) e.g. “\SampFolder”. Make sure that the ASPNet user has the create access to this folder.



Sample 1: Create a PDF file to a specified location dynamically.

4. Create a method e.g. sampleMethod(), call this method to create the PDF document in the above mentioned folder.

Private sub sampleMethod()
{

// step 1:
//Create an instance of a document.
Document document = new Document();

// step 2:
// we create a writer that listens to the document
// and directs a PDF-stream to a file
//Make sure that ASPNet user have create access to this folder
PdfWriter.GetInstance(document, new FileStream(@"c:\ SampFolder \test1.pdf", FileMode.Create));

// step 3: we open the document
document.Open();

// step 4: we create a table and add it to the document
Paragraph myParagraph = new Paragraph("Sample Text ", new Font(Font.TIMES_ROMAN, 8, Font.BOLD));
myParagraph.Add(new Paragraph("This way we can add formatted tables and text."));

iTextSharp.text.Table table = new iTextSharp.text.Table(3);
table.BorderWidth = 1;
table.BorderColor = new Color(0, 0, 255);
table.Padding = 5;
table.Spacing = 5;
Cell cell = new Cell("header");
cell.Header = true;
cell.Colspan = 3;
table.AddCell(cell);
cell = new Cell("example cell with colspan 1 and rowspan 2");
cell.Rowspan = 2;
cell.BorderColor = new Color(255, 0, 0);
table.AddCell(cell);
table.AddCell("1.1");
table.AddCell("2.1");
table.AddCell("1.2");
table.AddCell("2.2");
table.AddCell("cell test1");
cell = new Cell(myParagraph);
cell.Rowspan = 2;
cell.Colspan = 2;
cell.BackgroundColor = new Color(0xC0, 0xC0, 0xC0);
table.AddCell(cell);
table.AddCell("cell test2");
document.Add(table);
document.Close();
}

Sample 2: Export a dataset/ HTML Table to a PDF document.

5. Create another method ExportToPDF (page Pg), call this method to generate a PDF document by passing a page object as a parameter.

The parameter (Pg) is the name of the page calling the ExportToPDF() function.

As an example, here in this case the ExportToPDF method will be invoked as follows:
ExportToPDF (PdfReport)

Step 1:

public void ExportToPDF(Page pg)
{
//Creates an instance of the iTextSharp.text.Document-object:
Document document = new Document(PageSize.A4, 80, 50, 30, 65);

HTMLWorker worker = new HTMLWorker(document);

//call this method to get the data to be exported as a memory stream
MemoryStream mem = GetMemoryStream ();

MemoryStream m = new MemoryStream();
PdfWriter.GetInstance(document, m);

pg.Response.Clear();
pg.Response.AddHeader("content-disposition", "attachment;filename = Test.pdf");
pg.Response.ContentType = "application/pdf";

string htmlOutput = Encoding.UTF8.GetString(mem.GetBuffer());

// add metadata attributes to PDF doc
document.AddTitle("Sample Title");
document.AddSubject("Sample PDF export");
document.AddKeywords("Sample");

document.Open();
document.NewPage();
worker.Parse(new StringReader(htmlOutput));
document.Close();

// Write PDF bytes to outputstream
pg.Response.OutputStream.Write(m.GetBuffer(), 0, m.GetBuffer().Length);
m.Close();
mem.Close();
pg.Response.End();
}

Step2:

Get the required data (as a HTML document) into a memory stream as shown below.

private MemoryStream GetMemoryStream()
{

MemoryStream mem = new MemoryStream();
System.IO.StreamWriter pdfDoc;
pdfDoc = new System.IO.StreamWriter(mem);
pdfDoc.Write("<html><head><title>Sample PDF Exporter</title>");
pdfDoc.Write("</head>");
pdfDoc.Write("<body style='tab-interval:.5in'>");
//Get the string Builder Containing the Data from Database
pdfDoc.Write(GetReportData());
pdfDoc.Write("</body></html>");
pdfDoc.Close();
return mem;
}

Step 3:

Create a Method GetReportData() which returns a string containing a HTML document created using the StringBuilder class.

The string returned will contain the data to be exported to the PDF document. (The data is retrieved in the form of a dataset or a html table)

private string GetReportData()
{

String strOpenTableRowData = "<tr><td colSpan='2'>";
String strCloseTableRowData = "</td></tr>";
String strEmptyTableRowData = "<tr><td colspan='2'> </td></tr>";
StringBuilder strSampleReport = new StringBuilder();

// Build a html table using html tags embed our data from database.
strSampleReport.Append("<table>");
strSampleReport.Append(strOpenTableRowData);
strSampleReport.Append(strEmptyTableRowData);
strSampleReport.Append(strOpenTableRowData);
strSampleReport.Append(“Get Some Data Here To Export as a table”);
strSampleReport.Append(strEmptyTableRowData);
strSampleReport.Append(strCloseTableRowData);
strSampleReport.Append("</table>");

return strSampleReport.ToString();

}


Finally you can export the entire HTML data (retrieved as a String) to the PDF document by calling the ExportToPDF() method. You can also include metadata information like Title, Author, Keywords .etc. to the exported PDF document.

Using this component one can embed an image file easily. It is also possible to get an instance of an image in an array of bytes (having the binary image data) using the iTextSharp.text.Image object.



3. Advantages

Using this component, the dependency on Third Party Tools can be eliminated. This component also provides many properties for formatting the PDF document.
We can easily embed images, anchor tags, formatting texts, Header and footers, Graphics and HTML elements in the PDF document dynamically.

This component can be used effectively both in Web and Windows .NET applications.

You can also generate pdf from the gridview directly
public void generatePdf()
{
HtmlForm frm = new HtmlForm();
this.Controls.Add(frm);
{
frm.Controls.Add(grdPatientList);
}
Page.Response.Clear();
Response.AddHeader("content-disposition","attachment;filename=GridViewExport.pdf");
Response.Charset = "";
Response.ContentType = "application/pdf";
StringWriter stringWrite = new StringWriter();
HtmlTextWriter htmlWrite = new HtmlTextWriter(stringWrite);
frm.RenderControl(htmlWrite);
StringReader sr = new StringReader(stringWrite.ToString());
Document pdfDoc = new Document(PageSize.A4, 10f, 10f, 10f, 0f);
HTMLWorker htmlparser = new HTMLWorker(pdfDoc);
PdfWriter.GetInstance(pdfDoc, Response.OutputStream);
pdfDoc.Open();
htmlparser.Parse(sr);
pdfDoc.Close();
Response.Write(pdfDoc);
Response.End();
}
4. References

1. http://sourceforge.net/project/platformdownload.php?group_id=72954
2. http://itextsharp.sourceforge.net/tutorial/index.html

4 comments:

Asha said...

Hi Manab,

It is really very helpful and easy to understand.......

Thanku so much for this article...

OMaster said...

This is a great tutorial, but I cant make it work. The GetMemoryStream() always returns steam with zero lenght, no matter what I put into the GetReportData method.
Regards

Manab Ranjan Basu said...

I can work with that.any way ,I am sening you the full code that is working in PC.Just try to go with that....
Just modify the class name "pdfReport" at the begining

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using iTextSharp.text;
using iTextSharp.text.html.simpleparser;
using iTextSharp.text.pdf;
using System.IO;
using System.Text;



public partial class PdfReport : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{

ExportToPDF(this);
}

public void ExportToPDF(Page pg)
{
//Creates an instance of the iTextSharp.text.Document-object:
Document document = new Document(PageSize.A4, 80, 50, 30, 65);

HTMLWorker worker = new HTMLWorker(document);

//call this method to get the data to be exported as a memory stream
MemoryStream mem = GetMemoryStream();

MemoryStream m = new MemoryStream();
PdfWriter.GetInstance(document, m);

pg.Response.Clear();
pg.Response.AddHeader("content-disposition", "attachment;filename = Test.pdf");
pg.Response.ContentType = "application/pdf";

string htmlOutput = Encoding.UTF8.GetString(mem.GetBuffer());

// add metadata attributes to PDF doc
document.AddTitle("Sample Title");
document.AddSubject("Sample PDF export");
document.AddKeywords("Sample");

document.Open();
document.NewPage();
worker.Parse(new StringReader(htmlOutput));
document.Close();

// Write PDF bytes to outputstream
pg.Response.OutputStream.Write(m.GetBuffer(), 0, m.GetBuffer().Length);
m.Close();
mem.Close();
pg.Response.End();
}
private MemoryStream GetMemoryStream()
{
MemoryStream mem = new MemoryStream();
System.IO.StreamWriter pdfDoc;
pdfDoc = new System.IO.StreamWriter(mem);
pdfDoc.Write("<html><head><title>Sample PDF Exporter</title>");
pdfDoc.Write("</head>");
pdfDoc.Write("<body style='tab-interval:.5in'>");
//Get the string Builder Containing the Data from Database
pdfDoc.Write(GetReportData());
pdfDoc.Write("</body></html>");
pdfDoc.Close();
return mem;

}
private string GetReportData()
{

String strOpenTableRowData = "<tr><td colSpan='2'>";
String strCloseTableRowData = "</td></tr>";
String strEmptyTableRowData = "<tr><td colspan='2'> </td></tr>";
StringBuilder strSampleReport = new StringBuilder();

// Build a html table using html tags embed our data from database.
strSampleReport.Append("<table>");
strSampleReport.Append(strOpenTableRowData);
strSampleReport.Append(strEmptyTableRowData);
strSampleReport.Append(strOpenTableRowData);
strSampleReport.Append("Get Some Data Here To Export as a table");
strSampleReport.Append(strEmptyTableRowData);
strSampleReport.Append(strCloseTableRowData);
strSampleReport.Append("</table>");

return strSampleReport.ToString();

}


}

joeller said...

generatePdf() does not work pdfdoc.close() always produces error document has no pages even though the stringreader is populated with the html of my control.