In one of my previous articles I explained Export GridView To Word/Excel/PDF/CSV in ASP.Net.
 
 
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.
GridView displaying the records
 
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.
Exported PDf Document which has column widths same as that of the ASP.Net 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