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

 

This completes the article. Have a look at the Live Demo Here

To download iTextSharp Library click here.

You can download the related source code in VB.Net and C# using the link below

ExportGridViewToPDF.zip (1.15 mb)