Issue
But many users reported an issue with Export to PDF that iTextSharp ignores the GridView column widths. While researching I found that ITextSharp does not recognize some CSS styles hence specifying column widths in GridView was not going to work.
Solution
After going through the iTextSharp
tutorial. I found that we can create Tables with ITextSharp library and specify the column width and height as per our requirements. Thus we can create an ITextSharp table with same number of rows and columns as our GridView and specify the column widths for that ITextSharp table. This ensures that the custom column widths that we specify are not ignored in the generated PDF.
Namespaces
We would require the following namespaces in order to run this project.
C#
using System.Data;
using System.Data.SqlClient;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.html;
using iTextSharp.text.html.simpleparser;
using System.Text;
VB.Net
Imports System.Data
Imports System.Data.SqlClient
Imports System.IO
Imports iTextSharp.text
Imports iTextSharp.text.pdf
Imports iTextSharp.text.html
Imports iTextSharp.text.html.simpleparser
Imports System.Text
Front End Design
In the front end I have placed an ASP.Net GridView Control, a button for exporting and a RadioButtonList to allow the user to select whether he wants the current page to be exported to PDF or all the pages.
<asp:GridView ID="GridView1" runat="server"
AutoGenerateColumns = "false" Font-Names = "Arial"
Font-Size = "11pt" AlternatingRowStyle-BackColor = "#C2D69B"
HeaderStyle-BackColor = "green" AllowPaging ="true"
OnPageIndexChanging = "OnPaging" >
<Columns>
<asp:BoundField ItemStyle-Width = "200px"
DataField = "CustomerID" HeaderText = "CustomerID" />
<asp:BoundField ItemStyle-Width = "100px"
DataField = "City" HeaderText = "City"/>
<asp:BoundField ItemStyle-Width = "50px"
DataField = "Country" HeaderText = "Country"/>
</Columns>
</asp:GridView>
Binding the GridView
For this article I am using the NorthWind Database which can be downloaded from
here.
And I am binding the GridView using the following code snippet in the page load event. You will notice I have set different widths to the GridView columns.
C#
protected void Page_Load(object sender, EventArgs e)
{
String strConnString = ConfigurationManager.ConnectionStrings["conString"].ConnectionString;
SqlConnection con = new SqlConnection(strConnString);
SqlCommand cmd = new SqlCommand();
SqlDataAdapter sda = new SqlDataAdapter();
DataSet ds = new DataSet();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "select CustomerID,City,Country from customers";
cmd.Connection = con;
sda.SelectCommand = cmd;
try
{
con.Open();
sda.Fill(ds);
GridView1.EmptyDataText = "No Records Found";
GridView1.DataSource = ds;
GridView1.DataBind();
}
catch (Exception ex)
{
throw ex;
}
finally
{
con.Close();
con.Dispose();
}
}
VB.Net
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim strConnString As String = ConfigurationManager.ConnectionStrings("conString").ConnectionString
Dim con As New SqlConnection(strConnString)
Dim cmd As New SqlCommand()
Dim sda As New SqlDataAdapter()
Dim ds As New DataSet()
cmd.CommandType = CommandType.Text
cmd.CommandText = "select CustomerID,City,Country from customers"
cmd.Connection = con
sda.SelectCommand = cmd
Try
con.Open()
sda.Fill(ds)
GridView1.EmptyDataText = "No Records Found"
GridView1.DataSource = ds
GridView1.DataBind()
Catch ex As Exception
Throw ex
Finally
con.Close()
con.Dispose()
End Try
End Sub
When you run the application you will see the following output.
Now we will have to write the code on the click event of the Export Button as shown below.
C#
protected void btnExportPDF_Click(object sender, EventArgs e)
{
GridView1.AllowPaging = Convert.ToBoolean(rbPaging.SelectedItem.Value);
GridView1.DataBind();
//Create a table
iTextSharp.text.Table table = new iTextSharp.text
.Table(GridView1.Columns.Count);
table.Cellpadding = 5;
//Set the column widths
int[] widths = new int[GridView1.Columns.Count];
for (int x = 0; x < GridView1.Columns.Count; x++)
{
widths[x] = (int)GridView1.Columns[x].ItemStyle.Width.Value ;
string cellText = Server.HtmlDecode(GridView1.HeaderRow.Cells[x].Text);
iTextSharp.text.Cell cell = new iTextSharp.text.Cell(cellText);
cell.BackgroundColor = new Color (System.Drawing.ColorTranslator.FromHtml("#008000"));
table.AddCell(cell);
}
table.SetWidths(widths);
//Transfer rows from GridView to table
for (int i = 0; i < GridView1.Rows.Count; i++)
{
if (GridView1.Rows[i].RowType == DataControlRowType.DataRow)
{
for (int j = 0; j < GridView1.Columns.Count; j++)
{
string cellText = Server.HtmlDecode
(GridView1.Rows[i].Cells[j].Text);
iTextSharp.text.Cell cell = new iTextSharp.text.Cell(cellText);
//Set Color of Alternating row
if (i % 2 != 0)
{
cell.BackgroundColor = new Color(System.Drawing.ColorTranslator.FromHtml("#C2D69B"));
}
table.AddCell(cell);
}
}
}
//Create the PDF Document
Document pdfDoc = new Document(PageSize.A4, 10f, 10f, 10f, 0f);
PdfWriter.GetInstance(pdfDoc, Response.OutputStream);
pdfDoc.Open();
pdfDoc.Add(table);
pdfDoc.Close();
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment;" +
"filename=GridViewExport.pdf");
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Write(pdfDoc);
Response.End();
}
VB.Net
Protected Sub btnExportPDF_Click(ByVal sender As Object, ByVal e As EventArgs)
GridView1.AllowPaging = Convert.ToBoolean(rbPaging.SelectedItem.Value)
GridView1.DataBind()
'Create a table
Dim table As New iTextSharp.text.Table(GridView1.Columns.Count)
table.Cellpadding = 5
'Set the column widths
Dim widths As Integer() = New Integer(GridView1.Columns.Count - 1) {}
For x As Integer = 0 To GridView1.Columns.Count - 1
widths(x) = CInt(GridView1.Columns(x).ItemStyle.Width.Value)
Dim cellText As String = Server.HtmlDecode(GridView1.HeaderRow.Cells(x).Text)
Dim cell As New iTextSharp.text.Cell(cellText)
cell.BackgroundColor = New Color(System.Drawing.ColorTranslator.FromHtml("#008000"))
table.AddCell(cell)
Next
table.SetWidths(widths)
'Transfer rows from GridView to table
For i As Integer = 0 To GridView1.Rows.Count - 1
If GridView1.Rows(i).RowType = DataControlRowType.DataRow Then
For j As Integer = 0 To GridView1.Columns.Count - 1
Dim cellText As String = Server.HtmlDecode(GridView1.Rows(i).Cells(j).Text)
Dim cell As New iTextSharp.text.Cell(cellText)
'Set Color of Alternating row
If i Mod 2 <> 0 Then
cell.BackgroundColor = _
New Color(System.Drawing.ColorTranslator.FromHtml("#C2D69B"))
End If
table.AddCell(cell)
Next
End If
Next
'Create the PDF Document
Dim pdfDoc As New Document(PageSize.A4, 10.0F, 10.0F, 10.0F, 0.0F)
PdfWriter.GetInstance(pdfDoc, Response.OutputStream)
pdfDoc.Open()
pdfDoc.Add(table)
pdfDoc.Close()
Response.ContentType = "application/pdf"
Response.AddHeader("content-disposition", "attachment;filename=GridViewExport.pdf")
Response.Cache.SetCacheability(HttpCacheability.NoCache)
Response.Write(pdfDoc)
Response.End()
End Sub
As you will notice above I am looping through the GridView and creating cells in the iTextSharp table using the values from the GridView cells. Finally I am adding the table to the PDF document object which is then exported through the Response Stream. The figure below displays the exported PDF document with the custom column widths same as that specified in the GridView Control.
Also you will need to add this event in order to avoid the following error.
Control 'GridView1' of type 'GridView' must be placed inside a form tag with runat=server.
C#
public override void VerifyRenderingInServerForm(Control control)
{
/* Verifies that the control is rendered */
}
VB.Net
Public Overloads Overrides Sub VerifyRenderingInServerForm(ByVal control As Control)
' Verifies that the control is rendered
End Sub
Downloads