Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Printing Multiple Pages and Tabular Printing

4.91/5 (17 votes)
23 Nov 2009CPOL3 min read 87.9K   8.7K  
In this article, I will discuss printing of tabular data in multiple pages.

form.jpg

Introduction

When I was learning .NET programming, I found printing difficult and tedious to learn. I grasped the fundamentals of printing quickly, but when it came to printing multiple pages and tabular printing, I often felt frustrated trying to understand and program through it. However, when I finally prepared my mind to master it, I realized that there is a little mathematical and logical trick that is involved in printing.

In this article, I will discuss the printing of tabular data in multiple pages. For this purpose, I am using my data source datagrid from database records in Microsoft SQL Server. However, my target is to be able to print any data source in tabular form. This can be done for data sources such as ListViews. So keep in mind that our intention is to print in tabular form, not program databases in this article. In addition, I will also include the code for printing individual records from a database.

When I wrote the article, I kept in my mind that we can also make reports and do printing using the Report Manager of Visual Studio and/or third party applications such as Crystal Reports. However, when we try to print and make a report for an application that does not involve databases, it will be better if we know the printing paradigm. So in this article, I will mainly concentrate on the mathematical geometry of the page.

Page Geometry

During printing, the first thing to consider is the geometry of the page. Since printing is similar to graphics drawing, we have to consider the page as our canvas. We notice that all the printing functions are done using similar functions of printing.

Image 2

A single page has height, width as well as the left, right, top, and bottom margins. First, we calculate the actual area of the page on which data can be printed.

C#
int top, bottom, left, right; 
left = psp.PageSettings.Margins.Top; 
right = psp.PageSettings.Margins.Bottom;
top = psp.PageSettings.Margins.Left; 
bottom = psp.PageSettings.Margins.Right; 
pagewidth = printDocument2.DefaultPageSettings.PaperSize.Width
        -printDocument1.DefaultPageSettings.Margins.Left -
        printDocument1.DefaultPageSettings.Margins.Right;
pageheight = printDocument2.DefaultPageSettings.PaperSize.Height -
    printDocument1.DefaultPageSettings.Margins.Top -
    printDocument1.DefaultPageSettings.Margins.Bottom;

In this, we calculate the boundaries area of the page.

Calculate the number of maximum rows to be printed in a single page. This is used for locating the number of pages for the data in the records (datagrid).

C#
//calculate approximate number of rows per page
rpp = (int)( 0.98 * ((pagewidth -
      (int)(e.Graphics.MeasureString(grv.Columns[1].HeaderText, fh).Height) )/
      (int)(sm.Height +10)));

Actual Printing

Column Heading

The first thing to be printed is the data heading from the data grid.

C#
int i;
//iterates through data in the array columns of the datagrid
for (i = 0; i < grv.Columns.Count; i++) {
e.Graphics.DrawString(grv.Columns[i].HeaderText, fh, Brushes.Black, new
PointF(left + sf.Width * i + 50, top + 50)); }
int j; 

Next, the records or the rows are printed.

Data Rows

Image 3

The data in the rows are printed sequentially through iteration.

C#
//prints rows in the datagrid in a single pages using rpp control
for (j = currentrow; j < Math.Min (rpp+currentrow , grv.Rows.Count )-1; j++)
{ int k;
for (k = 0; k < grv.Rows[j].Cells.Count; k++)
{ e.Graphics.DrawString(grv.Rows[j].Cells[k].Value.ToString().ToUpper(), ff,
Brushes.Black, new PointF(left + sf.Width * k + 50, top + 50 + (j +
1-currentrow) * (sm.Height + 10))); }
//sum is used for holding the total amount from datagrid which is later printed for total
sum += Convert.ToDouble(grv.Rows[j].Cells[grv.Rows[j].Cells.Count - 2].Value);
//draw the rectangle for each data row which together forms the table
e.Graphics.DrawRectangle(Pens.Black, new Rectangle((int)(left + 50),
    (int)(top + 50 + (j-currentrow ) * (10 + sm.Height)),
    (int)(left + sf.Width * (i - 1)), (int)(sm.Height + 10))); }

Printing Multiple Pages

The important code snippet in printing multiple pages, if needed, starts from the form declaration of the static variable:

C#
//used for counting the number of pages required to print the rows.
static int currentrow = 0;

It is important to declare it as static, since every time the printing procedure is incremented, it is incremented by the total number of rows to print in a single page calculated previously (rpp).

C#
//the current row is incremented by rrp
// (total number of rows to be printed in single page)
currentrow += rpp-1;

//used for checking if it reaches final page of the printing pages

//if true it prints total amount from the guest
//again the sum is also static variable
if (currentrow >= (grv.Rows.Count))
{
    e.Graphics.DrawString("Total: ", ff,
    Brushes.Blue, new PointF(left + 50 + 3 * (sm.Width + 10), top + 50 + rt.Height
    + 10)); e.Graphics.DrawString(sum.ToString("##,##.00 NKF"), ff,
    Brushes.Red, new PointF(left + 50 + 4 * (sm.Width + 10), top + 50 + rt.Height +
    10));
    e.Graphics.DrawLine(Pens.Blue, left + 50 + 4 *
    (sm.Width + 10), top + 50 + rt.Height + 10 + sm.Height, left + 50 + 4 *
    (sm.Width + 10) + e.Graphics.MeasureString(sum.ToString("##,##.0
    NKF"), ff).Width, top + 50 + rt.Height + 10 + sm.Height);
}

Image 4

Final Code

C#
//test if currentrow reaches bottom of the page, if true add additional page
if (currentrow >= grv.Rows.Count)
{ 
    e.HasMorePages = false;
     currentrow = 0; 
}
else 
{
    e.HasMorePages = true; 
}

During printing, when an additional page is added, the print page event handler is called automatically. This continues recursively until the whole data is printed.

Point of Interest

Finally, I found out that printing is also a lot of fun. In this article, I was mainly concerned about the printing capabilities, although the application involves simple database manipulation.

History

  • 7th October, 2009: Initial version.

License

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