65.9K
CodeProject is changing. Read more.
Home

Printing Selected Columns and Rows in a DataGrid

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.56/5 (20 votes)

Nov 30, 2006

2 min read

viewsIcon

134782

downloadIcon

12269

An article on printing selected columns and rows in a DataGrid.

Introduction

Existing articles about DataGrid printing can only print all columns and rows. Sometimes a user needs to print specific columns and rows in a DataGrid. Some cases can be as below:

  • There are a very high number of rows in a DataGrid and there is no need to print all of them.
  • Sum of the column widths may be longer than the page width and it is better to remove one or more columns while printing.
  • The user wants to filter the DataGrid contents and then print the filtered data.

So a class named PrintDG was implemented, and it can be used in an application. I have done it both for DataGrid and DataGridView, in C# and VB.NET.

Description

The main section of the code is the PrintDG class.

In the PrintDG, we have:

  • The SelectedColumns and AvailableColumns lists to hold column names.
  • A PrintDocument object named PrintDoc (with BeginPrint and PrintPage events handlers).
  • Four functions:
    • Print_DataGrid: 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.

Using the code

For using the PrintDG class, the DataGrid must have a TableSyle, dg.TableStyles[0]. In the Main Form, the DataGrid is filled with the 'Order' table of 'Northwind.mdb', and a TableStyle for the DataGrid is defined. In the PrintOption Form, the DataGrid columns, font, fore-color, and title can be selected by the user.

Here is a section of code in the PrintDoc_PrintPage event handler. It does the following tasks:

  • Loops through all rows in the DataView.
  • In the 'Print Selected Rows' mode, if current row not selected, then ignore it.
  • If it reaches the end of the page, then write page number and go to the next page. If it doesn't reach the end of page then:
  • If it is in a new page, then draw headers and columns (it checks to see if each column was selected by the user, if not, will skip it). 
  • Draw the column contents for the TextBoxColumn and BoolColumn (it checks to see if each column was selected by the user, if not, will skip it)
  • Draw the borders.
  • Calculate 'Rows per Page' for the first page.
// Print Current Page, Row by Row 
while (RowPos <= dv.Count - 1)
{
    if (!PrintAllRows && !dg.IsSelected(RowPos))
    {
        RowPos++;
        continue;
    }
    DataRowView oRow = dv[RowPos];
    if (nTop + nHeight >= e.MarginBounds.Height + e.MarginBounds.Top)
    {
        DrawFooter(e, RowsPerPage);
        NewPage = true;
        PageNo++;
        e.HasMorePages = true;
        return;
    }
    else
    {
        if (NewPage)
        {
            // Draw Header
            e.Graphics.DrawString(PrintTitle, 
                    new Font(PrintFont, FontStyle.Bold), 
                    Brushes.Black, e.MarginBounds.Left, 
                    e.MarginBounds.Top -
                    e.Graphics.MeasureString(PrintTitle, 
                    new Font(PrintFont, FontStyle.Bold), 
                    e.MarginBounds.Width).Height - 13);

            string s = DateTime.Now.ToLongDateString() + " " + 
                       DateTime.Now.ToShortTimeString();
            e.Graphics.DrawString(s, new Font(PrintFont, 
                    FontStyle.Bold), Brushes.Black, 
                    e.MarginBounds.Left + (e.MarginBounds.Width - 
                    e.Graphics.MeasureString(s, 
                    new Font(PrintFont, FontStyle.Bold), 
                    e.MarginBounds.Width).Width), e.MarginBounds.Top - 
                    e.Graphics.MeasureString(PrintTitle, 
                    new Font(new Font(PrintFont, FontStyle.Bold), 
                    FontStyle.Bold),
                    e.MarginBounds.Width).Height - 13);

            // Draw Columns
            nTop = e.MarginBounds.Top;
            i = 0;
            foreach (DataGridColumnStyle GridCol in 
                     dg.TableStyles[0].GridColumnStyles)
            {
                if (!PrintDG.SelectedColumns.Contains(GridCol.HeaderText))
                    continue;
                e.Graphics.FillRectangle(new SolidBrush(Color.LightGray), 
                        new Rectangle((int) ColumnLefts[i], 
                        nTop, (int) ColumnWidths[i], nHeight));
                e.Graphics.DrawRectangle(Pens.Black, 
                         new Rectangle((int) ColumnLefts[i], nTop,
                        (int) ColumnWidths[i], nHeight));
                e.Graphics.DrawString(GridCol.HeaderText, PrintFont, 
                        new SolidBrush(PrintFontColor), 
                        new RectangleF((int) ColumnLefts[i],nTop, 
                        (int) ColumnWidths[i], nHeight), StrFormat);

                i++;
            }
            NewPage = false;
        }
        nTop += nHeight;
        i = 0;
        // Draw Columns Contents
        foreach (DataGridColumnStyle oColumn in 
                 dg.TableStyles[0].GridColumnStyles)
        {
            if (!PrintDG.SelectedColumns.Contains(oColumn.HeaderText))
                continue;
            string cellval = oRow.Row[oColumn.MappingName].ToString().Trim();
            if (ColumnTypes[i].ToString() == 
               "System.Windows.Forms.DataGridTextBoxColumn")
            {
                // For the TextBox Column
                // Draw Content of TextBox Cell
                e.Graphics.DrawString(cellval, PrintFont, 
                        new SolidBrush(PrintFontColor),
                        new RectangleF((int) ColumnLefts[i], nTop, 
                        (int) ColumnWidths[i], nHeight), StrFormat);
            }
            else if (ColumnTypes[i].ToString() == 
                     "System.Windows.Forms.DataGridBoolColumn")
            {
                // For the CheckBox Column
                // Draw Content of CheckBox Cell
                ChkBox.Size = new Size(14, 14);
                ChkBox.Checked = (bool) (oRow.Row[oColumn.MappingName]);
                Bitmap oBitmap = new Bitmap((int) ColumnWidths[i], nHeight);
                Graphics oTempGraphics = Graphics.FromImage(oBitmap);
                oTempGraphics.FillRectangle(Brushes.White, 
                   new Rectangle(0, 0, oBitmap.Width, oBitmap.Height));
                ChkBox.DrawToBitmap(oBitmap, 
                        new Rectangle((int)((oBitmap.Width - ChkBox.Width) / 2), 
                        (int) ((oBitmap.Height - ChkBox.Height) / 2), 
                        ChkBox.Width, ChkBox.Height));
                e.Graphics.DrawImage(oBitmap, 
                  new Point((int) ColumnLefts[i], nTop));
            }
            e.Graphics.DrawRectangle(Pens.Black, 
                       new Rectangle((int) ColumnLefts[i], 
                       nTop, (int) ColumnWidths[i], nHeight));
            i++;
        }
    }
    RowPos++;
    // For the first page it calculates Rows per Page
    if (PageNo == 1) RowsPerPage++;
}

History

  • December 12, 2006: Bug fixed - When there is no selected row, then trying to set 'Rows to print' = 'Selected rows' might cause 'Division by zero' error message. (Thanks to khanhdl.)