Click here to Skip to main content
15,911,890 members
Articles / Programming Languages / C#
Article

Printing of DataGridView

Rate me:
Please Sign up or sign in to vote.
4.69/5 (75 votes)
31 Jul 2008CPOL3 min read 514.8K   47.9K   101   123
This article will print all the records in a datagridview in tabular form

Introduction

Few days ago, I had been working on an application, called Fee Management System, which used to take the fee details from students and display the records on the basis of certain search criteria in a grid. Then the fee collector could print the entire details in the form of a report. Although, it was not a tedious task, the integration of printing with the application took most of the time. So, I thought of sharing my code with all the other developers who are working on the printing of datagridview.

Using the Code

To simplify things, I made a sample application and used the Customers table of Northwind database. In this application, we will have a simple form that will have two button controls, one datagridview control and a print<code>document control. The form will look as under (Figure 1):

Image 1
Figure 1

On the click of Get Customer Details button, we will load the Company Name, Contact Name, Address, Postal Code and Phone from the Customers table on to the grid and with the help of the Print button, we will print all the records in the grid. The following code snippet will make a call to Customers table and load the data on to the grid:

C#
>//Start Code Snippet
-----------------------------------------------------------------------
#region Get Customer Details Button Click Event
/// <summary>
/// Handles the customer details button click
/// </summary>
/// <param name=""sender""></param>
/// <param name=""e""></param>
private void btnCustomerDetails_Click(object sender, EventArgs e)
{
    Cursor.Current = Cursors.WaitCursor;
    SqlConnection sqlConnection = null;
    SqlCommand sqlCommand = null;
    SqlDataReader sqlReader = null;

    try
    {
        string strQuery = "SELECT CompanyName, ContactName, Address, PostalCode,
            Phone FROM Customers";
        sqlConnection = new SqlConnection(strConnectionString);
        sqlConnection.Open();
        sqlCommand = new SqlCommand(strQuery, sqlConnection);
        sqlReader = sqlCommand.ExecuteReader();
        while (sqlReader.Read())
        {
            object[] row = { sqlReader[0], sqlReader[1], sqlReader[2], sqlReader[3],
            sqlReader[4] };
            dataGridView1.Rows.Add(row);
        }
    }
    catch (Exception exc)
    {
        MessageBox.Show(exc.Message, "Error", MessageBoxButtons.OK,
            MessageBoxIcon.Error);
        return;
    }
    finally
    {
        Cursor.Current = Cursors.Default;
        sqlConnection.Close();
        if (sqlReader != null)
        {
            sqlReader.Dispose();
            sqlReader = null;
        }
        if (sqlCommand != null)
        {
            sqlCommand.Dispose();
            sqlCommand = null;
        }
    }
}
#endregion
-----------------------------------------------------------------------
//End Code Snippet

After executing the above code sample, we will have the grid with more than 90 records as shown in Figure 2:

Image 2
Figure 2

And finally on click of Print button, we will print all the records in a tabular form as shown in Figure 3:

Image 3
Figure 3

The printdocument control plays a major role in this printing process. This control has a PrintPage event that will have all the logic of printing. The spacing between the cells, width of the cells, page margins are all handled in this event. Our print click button event handler will invoke the PrintDialog control and there we can set the printer, page and other settings. The following code sample will be used in the Print button click event:

C#
//Start Code Snippet
-----------------------------------------------------------------------
#region Print Button Click Event
/// <summary>
/// Handles the print button click event
/// </summary>
/// <param name=""sender""></param>
/// <param name=""e""></param>
private void btnPrint_Click(object sender, EventArgs e)
{           
    //Open the print dialog
    PrintDialog printDialog = new PrintDialog();            
    printDialog.Document = printDocument1;
    printDialog.UseEXDialog = true;    
    //Get the document
    if (DialogResult.OK == printDialog.ShowDialog())
    {
        printDocument1.DocumentName = "Test Page Print";                
        printDocument1.Print();
    }
    /*
    Note: In case you want to show the Print Preview Dialog instead of 
    Print Dialog then comment the above code and uncomment the following code
    */

    //Open the print preview dialog
    //PrintPreviewDialog objPPdialog = new PrintPreviewDialog();
    //objPPdialog.Document = printDocument1;
    //objPPdialog.ShowDialog();
}
#endregion
-----------------------------------------------------------------------
//End Code Snippet

So, the print button click will show the Print Dialog as shown in Figure 4:

Image 4
Figure 4

This is a standard print dialog and you can change the settings here. Now, on the click of Print button in Print Dialog control, the PrintPage event of printdocument gets invoked and prints all the records in the grid in tabular form as show in figure 4. The PrintDialog’s Document property is set to the printdocument control and to print the document, invoke the Print method of printDocument control. This will invoke the PrintPage event of printDocument. We have also handled the BeginPrint event of printDocument, where we formatted the string to be printed. The following code sample will be called from the BeginPrint event:

C#
//Start Code Snippet
-----------------------------------------------------------------------
#region Begin Print Event Handler
/// <summary>
/// Handles the begin print event of print document
/// </summary>
/// <param name=""sender""></param>
/// <param name=""e""></param>
private void printDocument1_BeginPrint(object sender,
    System.Drawing.Printing.PrintEventArgs e)
{
    try
    {
        strFormat = new StringFormat();
        strFormat.Alignment = StringAlignment.Near;
        strFormat.LineAlignment = StringAlignment.Center;
        strFormat.Trimming = StringTrimming.EllipsisCharacter;

        arrColumnLefts.Clear();
        arrColumnWidths.Clear();
        iCellHeight = 0;
        iCount = 0;
        bFirstPage = true;
        bNewPage = true;

        // Calculating Total Widths
        iTotalWidth = 0;
        foreach (DataGridViewColumn dgvGridCol in dataGridView1.Columns)
        {
            iTotalWidth += dgvGridCol.Width;
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}
#endregion
-----------------------------------------------------------------------
//End Code Snippet

And finally, we will call the PrintPage event which plays the crucial role in this printing process. The following code sample is used within the PrintPage event:

C#
//Start Code Snippet
-----------------------------------------------------------------------
#region Print Page Event
/// <summary>
/// Handles the print page event of print document
/// </summary>
/// <param name=""sender""></param>
/// <param name=""e""></param>
private void printDocument1_PrintPage(object sender,
    System.Drawing.Printing.PrintPageEventArgs e)
{
    try
    {
        //Set the left margin
        int iLeftMargin = e.MarginBounds.Left;
        //Set the top margin
        int iTopMargin = e.MarginBounds.Top;
        //Whether more pages have to print or not
        bool bMorePagesToPrint = false;
        int iTmpWidth = 0;             

        //For the first page to print set the cell width and header height
        if (bFirstPage)
        {
            foreach (DataGridViewColumn GridCol in dataGridView1.Columns)
            {
                iTmpWidth = (int)(Math.Floor((double)((double)GridCol.Width /
                    (double)iTotalWidth * (double)iTotalWidth *
                    ((double)e.MarginBounds.Width / (double)iTotalWidth))));

                iHeaderHeight = (int)(e.Graphics.MeasureString(GridCol.HeaderText,
                    GridCol.InheritedStyle.Font, iTmpWidth).Height) + 11;

                // Save width and height of headers
                arrColumnLefts.Add(iLeftMargin);
                arrColumnWidths.Add(iTmpWidth);
                iLeftMargin += iTmpWidth;
            }
        }
        //Loop till all the grid rows not get printed
        while (iRow <= dataGridView1.Rows.Count - 1)
        {
            DataGridViewRow GridRow = dataGridView1.Rows[iRow];
            //Set the cell height
            iCellHeight = GridRow.Height + 5;
            int iCount = 0;
            //Check whether the current page settings allows more rows to print
            if (iTopMargin + iCellHeight >= e.MarginBounds.Height + e.MarginBounds.Top)
            {
                bNewPage = true;
                bFirstPage = false;
                bMorePagesToPrint = true;
                break;
            }
            else
            {
                if (bNewPage)
                {
                    //Draw Header
                    e.Graphics.DrawString("Customer Summary", 
                        new Font(dataGridView1.Font, FontStyle.Bold),
                        Brushes.Black, e.MarginBounds.Left, 
                        e.MarginBounds.Top - e.Graphics.MeasureString("Customer Summary",
                        new Font(dataGridView1.Font,FontStyle.Bold),
                        e.MarginBounds.Width).Height - 13);

                    String strDate = DateTime.Now.ToLongDateString() + " " +
                        DateTime.Now.ToShortTimeString();
                    //Draw Date
                    e.Graphics.DrawString(strDate, 
                        new Font(dataGridView1.Font, FontStyle.Bold), Brushes.Black,
                        e.MarginBounds.Left + 
                        (e.MarginBounds.Width - e.Graphics.MeasureString (strDate, 
                        new Font(dataGridView1.Font, FontStyle.Bold),
                        e.MarginBounds.Width).Width), 
                        e.MarginBounds.Top - e.Graphics.MeasureString("Customer Summary",
                        new Font(new Font(dataGridView1.Font, FontStyle.Bold), 
                        FontStyle.Bold), e.MarginBounds.Width).Height - 13);

                    //Draw Columns                 
                    iTopMargin = e.MarginBounds.Top;
                    foreach (DataGridViewColumn GridCol in dataGridView1.Columns)
                    {
                        e.Graphics.FillRectangle(new SolidBrush(Color.LightGray),    
                            new Rectangle((int)arrColumnLefts[iCount], iTopMargin,
                            (int)arrColumnWidths[iCount], iHeaderHeight));

                        e.Graphics.DrawRectangle(Pens.Black,             
                            new Rectangle((int)arrColumnLefts[iCount], iTopMargin,
                            (int)arrColumnWidths[iCount], iHeaderHeight));

                        e.Graphics.DrawString(GridCol.HeaderText,
                            GridCol.InheritedStyle.Font,
                            new SolidBrush(GridCol.InheritedStyle.ForeColor),
                            new RectangleF((int)arrColumnLefts[iCount], iTopMargin,
                            (int)arrColumnWidths[iCount], iHeaderHeight), strFormat);
                        iCount++;
                    }
                    bNewPage = false;
                    iTopMargin += iHeaderHeight;
                }
                iCount = 0;
                //Draw Columns Contents                
                foreach (DataGridViewCell Cel in GridRow.Cells)
                {
                    if (Cel.Value != null)
                    {
                        e.Graphics.DrawString(Cel.Value.ToString(),
                            Cel.InheritedStyle.Font,
                            new SolidBrush(Cel.InheritedStyle.ForeColor),
                            new RectangleF((int)arrColumnLefts[iCount],
                            (float)iTopMargin,
                            (int)arrColumnWidths[iCount], (float)iCellHeight),
                            strFormat);
                    }
                    //Drawing Cells Borders 
                    e.Graphics.DrawRectangle(Pens.Black, 
                        new Rectangle((int)arrColumnLefts[iCount], iTopMargin,
                        (int)arrColumnWidths[iCount], iCellHeight)); 
                    iCount++;
                }
            }
            iRow++;
            iTopMargin += iCellHeight;                    
        }        
        //If more lines exist, print another page.
        if (bMorePagesToPrint)
            e.HasMorePages = true;
        else
            e.HasMorePages = false;
    }
    catch (Exception exc)
    {
        MessageBox.Show(exc.Message, "Error", MessageBoxButtons.OK,
           MessageBoxIcon.Error);
    }
}
#endregion
-----------------------------------------------------------------------
//End Code Snippet

Here it is. You can see how easy the printing of datagridview records is. The sample application is also attached for your reference. Let me know in case you have any queries/issues.

Happy programming!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Abhishek Pant31-Oct-12 10:31
professionalAbhishek Pant31-Oct-12 10:31 
GeneralMy vote of 5 Pin
Rahul Bhalekar29-Jul-12 19:42
Rahul Bhalekar29-Jul-12 19:42 
QuestionHow To add on Bottom Pin
musespratama4-Jul-12 17:00
musespratama4-Jul-12 17:00 
QuestionWhy post something that doesnt compile? or have declarations? Pin
EvoVix12-Jun-12 2:52
EvoVix12-Jun-12 2:52 
Questionhow can i change this code to print from rtl Pin
BR0K3R26-May-12 2:40
BR0K3R26-May-12 2:40 
QuestionBlank page when using Print Preview print option Pin
JanMain24-Feb-12 0:12
JanMain24-Feb-12 0:12 
QuestionWorking for the first page Pin
Jesus Jacques17-Mar-11 6:37
Jesus Jacques17-Mar-11 6:37 
AnswerRe: Working for the first page Pin
Member 971285427-Dec-12 2:49
Member 971285427-Dec-12 2:49 
For anyone reading this, I had the same thing when converting to VB.Net. The same solution applies to this post and my problem Smile | :)

At the end of this section of code in the C# variant - was a 'Break'.


VB
If (iTopMargin + iCellHeight >= e.MarginBounds.Height + e.MarginBounds.Top) Then
bNewPage = True
bFirstPage = False
bMorePagesToPrint = True
'MISSING C# BREAK (VB.NET EXIT WHILE)
Else


It needs an EXIT WHILE statement putting in.

Full working code in VB.NET

VB
Imports System.Drawing.Printing
Imports System
Imports System.Collections
Imports System.ComponentModel
Imports System.Data
Imports System.Text
Imports System.Windows.Forms
Imports System.Drawing

Public Class Form10

    Private WithEvents printDocument1 As New PrintDocument
    'Used to save left coordinates of columns
    Dim arrColumnLefts = New ArrayList()
    'Used to save column widths
    Dim arrColumnWidths = New ArrayList()
    'Used to get and set the datagridview cell height
    Dim iCellHeight As Integer = 0
    Dim iTotalWidth As Integer = 0
    'Used as counter
    Dim iCount As Integer = 0
    Dim iRow As Integer = 0
    'Used to check whether we are printing first page
    Dim bFirstPage As Boolean = False
    'Used to check whether we are printing a new page
    Dim bNewPage As Boolean = False
    'Used for the header height
    Dim iHeaderHeight As Integer = 0

    Dim strFormat = New StringFormat()

    Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
        'Open the print dialogue or print preview (swap out the commented section)
        'Open the print dialogue
        Dim MyPrintDialog = New PrintDialog()
        MyPrintDialog.Document = printDocument1
        MyPrintDialog.UseEXDialog = True
        'Get the document
        If DialogResult.OK = MyPrintDialog.ShowDialog() Then
            printDocument1.DocumentName = "Test page print"
            printDocument1.Print()
        End If

        'Code for print preview instead..
        'Open the print preview dialog
        'Dim objPPdialog = New PrintPreviewDialog()
        'objPPdialog.Document = printDocument1
        'objPPdialog.ShowDialog()
    End Sub



    Private Sub printDocument1_BeginPrint(sender As System.Object, e As System.Drawing.Printing.PrintEventArgs) Handles _
        printDocument1.BeginPrint
        MsgBox("starting printpage")
        Try

            strFormat.Alignment = StringAlignment.Near
            strFormat.LineAlignment = StringAlignment.Center
            strFormat.Trimming = StringTrimming.EllipsisCharacter

            arrColumnLefts.Clear()
            arrColumnWidths.Clear()
            iCellHeight = 0
            bFirstPage = True
            bNewPage = True

            'Calculating Total Widths
            iTotalWidth = 0

            For Each dgvGridCol As DataGridViewColumn In DataGridView1.Columns
                iTotalWidth = iTotalWidth + dgvGridCol.Width
            Next

        Catch ex As Exception
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try

    End Sub


    Private Sub printDocument1_PrintPage(sender As System.Object, e As System.Drawing.Printing.PrintPageEventArgs) Handles _
       printDocument1.PrintPage
        MsgBox("starting printpage")
        Try

            'Set the left margin
            Dim iLeftMargin As Integer = e.MarginBounds.Left
            'Set the top margin
            Dim iTopMargin As Integer = e.MarginBounds.Top
            'Whether more pages have to print or not
            Dim bMorePagesToPrint As Boolean = False
            Dim iTmpWidth As Integer = 0

            'For the first page to print set the cell width and header height
            If bFirstPage = True Then

                For Each Gridcol As DataGridViewColumn In DataGridView1.Columns
                    iTmpWidth = CType(Math.Floor(CType(CType(Gridcol.Width, Double) / CType(iTotalWidth, Double) * CType(iTotalWidth, Double) * (CType(e.MarginBounds.Width, Double) / CType(iTotalWidth, Double)), Double)), Integer)

                    iHeaderHeight = CType((e.Graphics.MeasureString(Gridcol.HeaderText, Gridcol.InheritedStyle.Font, iTmpWidth).Height) + 11, Integer)

                    'Save width and height of headers
                    arrColumnLefts.Add(iLeftMargin)
                    arrColumnWidths.Add(iTmpWidth)
                    iLeftMargin = iLeftMargin + iTmpWidth
                Next

            End If

            'Loop till all the grid rows not get printed
            While iRow <= DataGridView1.Rows.Count - 1

                Dim GridRow As DataGridViewRow = DataGridView1.Rows(iRow)
                'Set the cell height
                iCellHeight = GridRow.Height + 5
                Dim iCount As Integer = 0
                'Check whether the current page settings allo more rows to print

                If iTopMargin + iCellHeight >= e.MarginBounds.Height + e.MarginBounds.Top Then

                    bNewPage = True
                    bFirstPage = False
                    bMorePagesToPrint = True
                    '********* what should this be **********
                    Exit While

                Else

                    If bNewPage = True Then

                        'Draw header
                        e.Graphics.DrawString("Fibre Requirements", New Font(DataGridView1.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top - e.Graphics.MeasureString("Customer Summary", New Font(DataGridView1.Font, FontStyle.Bold), e.MarginBounds.Width).Height - 13)

                        Dim strDate As String = DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToShortTimeString()

                        'Draw Date
                        e.Graphics.DrawString(strDate, New Font(DataGridView1.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(strDate, New Font(DataGridView1.Font, FontStyle.Bold), e.MarginBounds.Width).Width), e.MarginBounds.Top - e.Graphics.MeasureString("Customer Summary", New Font(New Font(DataGridView1.Font, FontStyle.Bold), FontStyle.Bold), e.MarginBounds.Width).Height - 13)

                        'Draw Columns                 
                        iTopMargin = e.MarginBounds.Top

                        For Each GridCol As DataGridViewColumn In DataGridView1.Columns

                            e.Graphics.FillRectangle(New SolidBrush(Color.LightGray), New Rectangle(CType(arrColumnLefts(iCount), Integer), iTopMargin, CType(arrColumnWidths(iCount), Integer), iHeaderHeight))

                            e.Graphics.DrawRectangle(Pens.Black, New Rectangle(CType(arrColumnLefts(iCount), Integer), iTopMargin, CType(arrColumnWidths(iCount), Integer), iHeaderHeight))

                            e.Graphics.DrawString(GridCol.HeaderText, GridCol.InheritedStyle.Font, New SolidBrush(GridCol.InheritedStyle.ForeColor), New RectangleF(CType(arrColumnLefts(iCount), Integer), iTopMargin, CType(arrColumnWidths(iCount), Integer), iHeaderHeight), strFormat)
                            iCount = iCount + 1

                        Next GridCol

                        bNewPage = False
                        iTopMargin += iHeaderHeight

                    End If
                    iCount = 0

                    'Draw Columns Contents                
                    For Each Cel As DataGridViewCell In GridRow.Cells

                        If Not IsDBNull(Cel.Value) Then

                            e.Graphics.DrawString(Cel.Value.ToString(), Cel.InheritedStyle.Font, New SolidBrush(Cel.InheritedStyle.ForeColor), New RectangleF(CType(arrColumnLefts(iCount), Integer), CType(iTopMargin, Single), CType(arrColumnWidths(iCount), Integer), CType(iCellHeight, Single)), strFormat)

                        End If

                        'Drawing Cells Borders 
                        e.Graphics.DrawRectangle(Pens.Black, New Rectangle(CType(arrColumnLefts(iCount), Integer), iTopMargin, CType(arrColumnWidths(iCount), Integer), iCellHeight))

                        iCount = iCount + 1

                    Next

                End If

                iRow = iRow + 1
                iTopMargin = iTopMargin + iCellHeight

            End While

            'If more lines exist, print another page.
            If bMorePagesToPrint = True Then

                e.HasMorePages = True

            Else

                e.HasMorePages = False

            End If

        Catch exc As Exception

            MessageBox.Show(exc.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)

        End Try

    End Sub

End Class

GeneralRe: Working for the first page Pin
hanihanna8926-Jun-13 7:18
hanihanna8926-Jun-13 7:18 
Generalc++ Pin
jose.sutilo11-Oct-10 0:15
jose.sutilo11-Oct-10 0:15 
QuestionHow can i change the Y-Position of the datagridview in the printing document? Pin
Tobinho jr25-Sep-10 9:44
Tobinho jr25-Sep-10 9:44 
Questionprinting selected columns Pin
nitin944420-Sep-10 0:31
nitin944420-Sep-10 0:31 
JokeGr8 article. Helpful! Thanks! Pin
ben19787-May-10 23:03
ben19787-May-10 23:03 
GeneralThanks Pin
asmsoftware19-Apr-09 0:08
asmsoftware19-Apr-09 0:08 
GeneralPage blank Pin
Samb19852-Mar-09 6:42
Samb19852-Mar-09 6:42 
GeneralRe: Page blank Pin
duphrx12-Mar-09 9:02
duphrx12-Mar-09 9:02 
GeneralRe: Page blank Pin
duphrx12-Mar-09 12:12
duphrx12-Mar-09 12:12 
GeneralRe: Page blank Pin
Life with .NET12-Mar-09 18:42
Life with .NET12-Mar-09 18:42 
GeneralRe: Page blank Pin
Ronin1141-May-09 8:59
Ronin1141-May-09 8:59 
AnswerRe: Page blank Pin
jazzyj12320-Sep-09 11:56
jazzyj12320-Sep-09 11:56 
GeneralRe: Page blank Pin
feras.abulhaija2-Aug-12 11:09
feras.abulhaija2-Aug-12 11:09 
GeneralRe: Page blank Pin
Luis Javier Ramirez Torres21-Jun-15 21:52
Luis Javier Ramirez Torres21-Jun-15 21:52 
GeneralRe: Page blank Pin
Evord15-May-13 23:11
professionalEvord15-May-13 23:11 
GeneralErr msgs with code Pin
Clay Shannon11-Feb-09 6:58
Clay Shannon11-Feb-09 6:58 
GeneralRe: Err msgs with code Pin
Clay Shannon11-Feb-09 11:45
Clay Shannon11-Feb-09 11:45 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.