Click here to Skip to main content
11,644,731 members (60,619 online)
Click here to Skip to main content

DataGridView Printing by Selecting Columns and Rows

, 11 Mar 2007 CPOL 482.6K 33.6K 228
Rate this:
Please Sign up or sign in to vote.
An article on DataGrdView printing.

Introduction

Sometimes the user needs to print specific columns and rows (or all of them) in a DataGridView. Some cases can be as below:

  • There are too many rows in a DataGridView and there is no need to print all of them.
  • Sum of the column widths may be wider than the page width, and it is better to remove one or more columns while printing.

So a class named PrintDGV was implemented, and can be used in any .NET2.0 application. I have done it both for the DataGrid and for the DataGridView, in C# and VB.NET.

Description

The main section of the code is the PrintDGV class and the PrintOptions form.

In the PrintDGV, we have:

  • The SelectedColumns and AvailableColumns lists to hold column names.
  • A PrintDocument object named PrintDoc (with the BeginPrint and PrintPage event handlers)
  • Four functions:
    • Print_DataGridView: The main function that can be called from outside of the class.
    • PrintDoc_BeginPrint: Initializes some variables to begin printing.
    • PrintDoc_PrintPage: Performs the printing job.
    • DrawFooter: Writes the page number.

The code has the following features :

  • Supports TextBox, Link, Button, ComboBox, CheckBox, and Image columns.
  • Draws the columns to fit on the page width, or draws them as they are shown.
  • Wraps the cell text if the cell width is smaller than its contents.
  • Draws the page footer, date, time, and the title on the page.

Using the code

For using the code in an application, the PrintDGV class and the PrintOptions form must be added to it, and then the function Print_DataGridView is called. In our example, the sample project has a Form named MainForm.

In the MainForm, the DataGridView is filled with 'Persons' table of the 'Persongs.mdb'.

In the PrintOption form, the DataGridView Columns, Fitting to page, and the Title can be selected by user.

The PrintDoc_PrintPage event handler does the following tasks :

  • Calculates the column widths.
  • Prints the current page, row by row - loops through all rows in the DataGridView.
  • In the 'Print Selected Rows' mode, if the current row is not selected, then skips it.
  • If it reaches the end of the page, then writes the page number and goes to the next page. If it doesn't reach the end of the page then:
  • If it is in a new page, then draws the title, date-time, headers, and columns (checks to see if each column was selected by the user, if not, skips it).
  • Draws the column contents for the TextBox, Link, Button, CheckBox, ComboBox, and Image cells (checks to see if each column was selected by the user, if not, skips it).
  • Draws the borders.
  • Calculates the 'Rows per Page' for the first page.
  • Writes the page footer (page number).
private static void PrintDoc_PrintPage(object sender, 
        System.Drawing.Printing.PrintPageEventArgs e) 
{
    int tmpWidth, i;
    int tmpTop = e.MarginBounds.Top;
    int tmpLeft = e.MarginBounds.Left;
    int HeaderHeight=0;

    try 
    {            
        // Before starting first page, it saves
        // Width & Height of Headers and CoulmnType
        if (PageNo == 1) 
        {
            foreach (DataGridViewColumn GridCol in dgv.Columns)
            {
                if (!GridCol.Visible) continue;
                // Skip if the current column not selected
                if (!PrintDGV.SelectedColumns.Contains(
                     GridCol.HeaderText)) continue;

                // Detemining whether the columns
                // are fitted to the page or not.
                if (FitToPageWidth) 
                    tmpWidth = (int)(Math.Floor((double)(
                               (double)GridCol.Width / 
                               (double)TotalWidth * (double)TotalWidth * 
                               ((double)e.MarginBounds.Width / 
                                (double)TotalWidth))));
                else
                    tmpWidth = GridCol.Width;

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

                // Save width & height of headres and ColumnType
                ColumnLefts.Add(tmpLeft);
                ColumnWidths.Add(tmpWidth);
                ColumnTypes.Add(GridCol.GetType());
                tmpLeft += tmpWidth;
            }
        }

        // Printing Current Page, Row by Row
        while (RowPos <= dgv.Rows.Count - 1)
        {
            DataGridViewRow GridRow = dgv.Rows[RowPos];
            if (GridRow.IsNewRow || (!PrintAllRows && !GridRow.Selected))
            {
                RowPos++;
                continue;
            }

            CellHeight = GridRow.Height;

            if (tmpTop + CellHeight >= 
                 e.MarginBounds.Height + e.MarginBounds.Top)
            {
                DrawFooter(e, RowsPerPage);
                NewPage = true;
                PageNo++;
                e.HasMorePages = true;
                return;
            }
            else
            {
                if (NewPage)
                {
                    // Draw Print Title
                    e.Graphics.DrawString(PrintTitle, 
                           new Font(dgv.Font, FontStyle.Bold), 
                            Brushes.Black, e.MarginBounds.Left, 
                            e.MarginBounds.Top -
                            e.Graphics.MeasureString(PrintTitle, 
                            new Font(dgv.Font, 
                            FontStyle.Bold), 
                            e.MarginBounds.Width).Height - 13);

                    String s = DateTime.Now.ToLongDateString() + " " + 
                               DateTime.Now.ToShortTimeString();
                    // Draw Time and Date    
                    e.Graphics.DrawString(s, 
                            new Font(dgv.Font, FontStyle.Bold), 
                            Brushes.Black, e.MarginBounds.Left + 
                            (e.MarginBounds.Width - 
                            e.Graphics.MeasureString(s, new Font(dgv.Font, 
                            FontStyle.Bold), e.MarginBounds.Width).Width), 
                            e.MarginBounds.Top - 
                            e.Graphics.MeasureString(PrintTitle, 
                            new Font(new Font(dgv.Font, 
                            FontStyle.Bold), FontStyle.Bold), 
                            e.MarginBounds.Width).Height - 13);

                    // Draw Headers
                    tmpTop = e.MarginBounds.Top;
                    i = 0;
                    foreach (DataGridViewColumn GridCol in dgv.Columns)
                    {
                        if (!GridCol.Visible) continue;
                        if (!PrintDGV.SelectedColumns.Contains(
                                            GridCol.HeaderText)) 
                            continue;

                        e.Graphics.FillRectangle(new 
                            SolidBrush(Color.LightGray), 
                            new Rectangle((int) ColumnLefts[i], tmpTop,
                            (int)ColumnWidths[i], HeaderHeight));

                        e.Graphics.DrawRectangle(Pens.Black, 
                            new Rectangle((int) ColumnLefts[i], tmpTop,
                            (int)ColumnWidths[i], HeaderHeight));

                        e.Graphics.DrawString(GridCol.HeaderText, 
                            GridCol.InheritedStyle.Font, 
                            new SolidBrush(GridCol.InheritedStyle.ForeColor),
                            new RectangleF((int)ColumnLefts[i], tmpTop, 
                            (int)ColumnWidths[i], HeaderHeight), StrFormat);
                        i++;
                    }
                    NewPage = false;
                    tmpTop += HeaderHeight;
                }

                // Draw Columns Contents
                i = 0;
                foreach (DataGridViewCell Cel in GridRow.Cells)
                {
                    if (!Cel.OwningColumn.Visible) continue;
                    if (!SelectedColumns.Contains(
                            Cel.OwningColumn.HeaderText))
                        continue;

                    // For the TextBox Column
                    if (((Type) ColumnTypes[i]).Name == 
                         "DataGridViewTextBoxColumn" || 
                        ((Type) ColumnTypes[i]).Name == 
                         "DataGridViewLinkColumn")
                    {
                        e.Graphics.DrawString(Cel.Value.ToString(), 
                                Cel.InheritedStyle.Font, 
                                new SolidBrush(Cel.InheritedStyle.ForeColor),
                                new RectangleF((int)ColumnLefts[i], 
                                (float)tmpTop,
                                (int)ColumnWidths[i], 
                                (float)CellHeight), StrFormat);
                    }
                    // For the Button Column
                    else if (((Type) ColumnTypes[i]).Name == 
                                     "DataGridViewButtonColumn")
                    {
                        CellButton.Text = Cel.Value.ToString();
                        CellButton.Size = new Size((int)ColumnWidths[i], 
                                                    CellHeight);
                        Bitmap bmp = new Bitmap(CellButton.Width, 
                                                CellButton.Height);
                        CellButton.DrawToBitmap(bmp, new Rectangle(0, 0, 
                                bmp.Width, bmp.Height));
                        e.Graphics.DrawImage(bmp, 
                          new Point((int)ColumnLefts[i], tmpTop));
                    }
                    // For the CheckBox Column
                    else if (((Type) ColumnTypes[i]).Name == 
                              "DataGridViewCheckBoxColumn")
                    {
                        CellCheckBox.Size = new Size(14, 14);
                        CellCheckBox.Checked = (bool)Cel.Value;
                        Bitmap bmp = new Bitmap((int)ColumnWidths[i], 
                                                 CellHeight);
                        Graphics tmpGraphics = Graphics.FromImage(bmp);
                        tmpGraphics.FillRectangle(Brushes.White, 
                                new Rectangle(0, 0, 
                                bmp.Width, bmp.Height));
                        CellCheckBox.DrawToBitmap(bmp, 
                                new Rectangle((int)((bmp.Width - 
                                CellCheckBox.Width) / 2), 
                                (int)((bmp.Height - CellCheckBox.Height) / 2), 
                                CellCheckBox.Width, CellCheckBox.Height));
                        e.Graphics.DrawImage(bmp, 
                                new Point((int)ColumnLefts[i], tmpTop));
                    }
                    // For the ComboBox Column
                    else if (((Type) ColumnTypes[i]).Name == 
                              "DataGridViewComboBoxColumn")
                    {
                        CellComboBox.Size = new Size((int)ColumnWidths[i], 
                                                CellHeight);
                        Bitmap bmp = new Bitmap(CellComboBox.Width, 
                                                CellComboBox.Height);
                        CellComboBox.DrawToBitmap(bmp, new Rectangle(0, 0, 
                                bmp.Width, bmp.Height));
                        e.Graphics.DrawImage(bmp, 
                                new Point((int)ColumnLefts[i], tmpTop));
                        e.Graphics.DrawString(Cel.Value.ToString(), 
                                Cel.InheritedStyle.Font, 
                                new SolidBrush(Cel.InheritedStyle.ForeColor), 
                                new RectangleF((int)ColumnLefts[i] + 1, 
                                tmpTop, (int)ColumnWidths[i]
                                - 16, CellHeight), StrFormatComboBox);
                    }
                    // For the Image Column
                    else if (((Type) ColumnTypes[i]).Name == 
                              "DataGridViewImageColumn")
                    {
                        Rectangle CelSize = new Rectangle((int)ColumnLefts[i], 
                                tmpTop, (int)ColumnWidths[i], CellHeight);
                        Size ImgSize = ((Image)(Cel.FormattedValue)).Size;
                        e.Graphics.DrawImage((Image)Cel.FormattedValue, 
                                new Rectangle((int)ColumnLefts[i] + 
                                (int)((CelSize.Width - ImgSize.Width) / 2), 
                                tmpTop + (int)((CelSize.Height - 
                                ImgSize.Height) / 2), 
                                ((Image)(Cel.FormattedValue)).Width, 
                                ((Image)(Cel.FormattedValue)).Height));

                    }

                    // Drawing Cells Borders 
                    e.Graphics.DrawRectangle(Pens.Black, 
                            new Rectangle((int)ColumnLefts[i], 
                            tmpTop, (int)ColumnWidths[i], CellHeight));

                    i++;

                }
                tmpTop += CellHeight;
            }

            RowPos++;
            // For the first page it calculates Rows per Page
            if (PageNo == 1) RowsPerPage++;
        }

        if (RowsPerPage == 0) return;

        // Write Footer (Page Number)
        DrawFooter(e, RowsPerPage);

        e.HasMorePages = false;
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Error", 
                        MessageBoxButtons.OK, 
                        MessageBoxIcon.Error);
    }
}

History

Two bugs fixed (22 Feb 2007):

  • The number of pages in the C# code was wrong.
  • For the pages after the first page, the column headers were overwriting the first row ( both in the C# code and the VB code).

License

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

Share

About the Author

Afrasiab Cheraghi
Web Developer
Iran (Islamic Republic Of) Iran (Islamic Republic Of)
No Biography provided

You may also be interested in...

Comments and Discussions

 
Questioncan we use excel file as database insisted of access Pin
Member 1027329324-Jul-15 21:23
memberMember 1027329324-Jul-15 21:23 
QuestionSir Two Questions Pin
Rose4203-Oct-14 1:43
memberRose4203-Oct-14 1:43 
QuestionSelect Printer Pin
Member 102755607-Sep-14 16:58
memberMember 102755607-Sep-14 16:58 
Questionquestion Pin
Member 109300397-Jul-14 7:49
memberMember 109300397-Jul-14 7:49 
QuestionDataGridView Cell is empty -> object reference not set to an instance of an object Pin
Member 885789712-Feb-14 3:32
memberMember 885789712-Feb-14 3:32 
AnswerRe: DataGridView Cell is empty -> object reference not set to an instance of an object Pin
Member 885789712-Feb-14 20:18
memberMember 885789712-Feb-14 20:18 
QuestionNice post Pin
Tridip Bhattacharjee12-Dec-13 21:50
memberTridip Bhattacharjee12-Dec-13 21:50 
QuestionDataGridView Printing by Selecting Columns and Rows Pin
Cheeky22-Sep-13 10:20
memberCheeky22-Sep-13 10:20 
SuggestionDataGridView Printing by Selecting Columns and Rows Pin
Cheeky22-Sep-13 10:18
memberCheeky22-Sep-13 10:18 
Questionhow can I adjust size of cells? Pin
babak146-Sep-13 1:45
memberbabak146-Sep-13 1:45 
QuestionAfra, I have could you email me? Pin
Steve_Scott111-Jun-13 23:30
memberSteve_Scott111-Jun-13 23:30 
Generalawesome Pin
ajit_machhe2-Jun-13 9:47
memberajit_machhe2-Jun-13 9:47 
QuestionHow can I get a sum for each of the columns in all the rows in a datatable and place them in the last row Pin
Kibika23-Apr-13 9:32
memberKibika23-Apr-13 9:32 
QuestionPrinting Datagridview: How do I calculate sum of a column and place the answer in the last row Pin
Kibika20-Apr-13 8:40
memberKibika20-Apr-13 8:40 
QuestionAgain--Top notch--can the column headers text be centered? Pin
Member 998224013-Apr-13 7:09
memberMember 998224013-Apr-13 7:09 
AnswerRe: Again--Top notch--can the column headers text be centered? Pin
Member 998224013-Apr-13 16:47
memberMember 998224013-Apr-13 16:47 
QuestionAwesome code: One question about some formatting Pin
Member 998224012-Apr-13 16:20
memberMember 998224012-Apr-13 16:20 
GeneralMy vote of 5 Pin
Member 998224012-Apr-13 16:18
memberMember 998224012-Apr-13 16:18 
QuestionRemove the time portion from printing Pin
Igor Vasilachi21-Mar-13 20:44
memberIgor Vasilachi21-Mar-13 20:44 
AnswerRe: Remove the time portion from printing Pin
Matthew Buchman2-Oct-13 23:49
memberMatthew Buchman2-Oct-13 23:49 
QuestionNo specific lines view selected for printing Pin
Luis Antonio LAHA21-Mar-13 6:19
memberLuis Antonio LAHA21-Mar-13 6:19 
GeneralThanks. Pin
Programmer 18-Jan-13 1:43
memberProgrammer 18-Jan-13 1:43 
QuestionPage ranges Pin
Tarianx20-Dec-12 7:14
memberTarianx20-Dec-12 7:14 
QuestionProblem in printing Right-to-Left Arabic content Pin
Member 792546631-May-12 0:37
memberMember 792546631-May-12 0:37 
QuestionAdd Some Information above the Printed Page Pin
Lavneet Sharma25-May-12 22:35
memberLavneet Sharma25-May-12 22:35 
QuestionPrinting Orientation - Landscape Pin
Member 884930418-Apr-12 20:38
memberMember 884930418-Apr-12 20:38 
AnswerRe: Printing Orientation - Landscape Pin
antcargui1-Feb-13 3:32
memberantcargui1-Feb-13 3:32 
GeneralRe: Printing Orientation - Landscape Pin
Member 1035373924-Nov-13 22:28
memberMember 1035373924-Nov-13 22:28 
AnswerRe: Printing Orientation - Landscape Pin
victor medrano21-Dec-14 15:09
membervictor medrano21-Dec-14 15:09 
QuestionBackColor in Cells Pin
dercode28-Mar-12 6:37
memberdercode28-Mar-12 6:37 
QuestionHelp with positioning text in columns Pin
Cheeky4-Mar-12 9:14
memberCheeky4-Mar-12 9:14 
QuestionPrinter Select Pin
Member 850460829-Feb-12 3:29
memberMember 850460829-Feb-12 3:29 
GeneralMy vote of 5 Pin
manoj kumar choubey16-Feb-12 1:58
membermanoj kumar choubey16-Feb-12 1:58 
GeneralMy vote of 5 Pin
Member 850460823-Dec-11 3:22
memberMember 850460823-Dec-11 3:22 
QuestionPse, in VB 2010 Pin
Baldomero12316-Dec-11 23:34
memberBaldomero12316-Dec-11 23:34 
QuestionPse in VB language Pin
Baldomero12316-Dec-11 23:32
memberBaldomero12316-Dec-11 23:32 
AnswerModification to allow image aspect ratio to be maintained. Pin
kasbaba22-Nov-11 0:27
memberkasbaba22-Nov-11 0:27 
QuestionHow to reduce the banks of the document? Pin
Member 827112315-Nov-11 23:01
memberMember 827112315-Nov-11 23:01 
Questionproblem with printing text Pin
mrichard10121-Sep-11 2:57
membermrichard10121-Sep-11 2:57 
GeneralMy vote of 5 Pin
Denver Bright27-Aug-11 11:03
memberDenver Bright27-Aug-11 11:03 
GeneralMy vote of 5 Pin
Ehsan Salmanpour24-Aug-11 23:12
memberEhsan Salmanpour24-Aug-11 23:12 
Questionprint right to left datagrid Pin
Afinazar3-Aug-11 1:59
memberAfinazar3-Aug-11 1:59 
GeneralPrinting Grid columns based on the columns count Pin
meha2330-May-11 20:30
membermeha2330-May-11 20:30 
GeneralGreat work buddy.. Pin
sajan_engineer31-Mar-11 17:28
membersajan_engineer31-Mar-11 17:28 
GeneralMy vote of 5 Pin
Member 390047628-Mar-11 9:39
memberMember 390047628-Mar-11 9:39 
Questionhow can i use printdgv.cs in my exit project Pin
por77722-Mar-11 16:08
memberpor77722-Mar-11 16:08 
AnswerRe: how can i use printdgv.cs in my exit project Pin
Du Sijun7-Aug-11 18:51
memberDu Sijun7-Aug-11 18:51 
GeneralMy vote of 5 Pin
SurajMutha10-Feb-11 14:23
memberSurajMutha10-Feb-11 14:23 
GeneralPrinter Select Pin
dj_maverick31-Jan-11 8:08
memberdj_maverick31-Jan-11 8:08 
GeneralRe: Printer Select Pin
dj_maverick4-Feb-11 7:15
memberdj_maverick4-Feb-11 7:15 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150731.1 | Last Updated 11 Mar 2007
Article Copyright 2006 by Afrasiab Cheraghi
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid