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):
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:
>
-----------------------------------------------------------------------
#region Get Customer Details Button Click Event
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
-----------------------------------------------------------------------
After executing the above code sample, we will have the grid with more than 90 records as shown in Figure 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:
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:
-----------------------------------------------------------------------
#region Print Button Click Event
private void btnPrint_Click(object sender, EventArgs e)
{
PrintDialog printDialog = new PrintDialog();
printDialog.Document = printDocument1;
printDialog.UseEXDialog = true;
if (DialogResult.OK == printDialog.ShowDialog())
{
printDocument1.DocumentName = "Test Page Print";
printDocument1.Print();
}
}
#endregion
-----------------------------------------------------------------------
So, the print button click will show the Print Dialog as shown in Figure 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:
-----------------------------------------------------------------------
#region Begin Print Event Handler
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;
iTotalWidth = 0;
foreach (DataGridViewColumn dgvGridCol in dataGridView1.Columns)
{
iTotalWidth += dgvGridCol.Width;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
#endregion
-----------------------------------------------------------------------
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:
-----------------------------------------------------------------------
#region Print Page Event
private void printDocument1_PrintPage(object sender,
System.Drawing.Printing.PrintPageEventArgs e)
{
try
{
int iLeftMargin = e.MarginBounds.Left;
int iTopMargin = e.MarginBounds.Top;
bool bMorePagesToPrint = false;
int iTmpWidth = 0;
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;
arrColumnLefts.Add(iLeftMargin);
arrColumnWidths.Add(iTmpWidth);
iLeftMargin += iTmpWidth;
}
}
while (iRow <= dataGridView1.Rows.Count - 1)
{
DataGridViewRow GridRow = dataGridView1.Rows[iRow];
iCellHeight = GridRow.Height + 5;
int iCount = 0;
if (iTopMargin + iCellHeight >= e.MarginBounds.Height + e.MarginBounds.Top)
{
bNewPage = true;
bFirstPage = false;
bMorePagesToPrint = true;
break;
}
else
{
if (bNewPage)
{
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();
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);
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;
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);
}
e.Graphics.DrawRectangle(Pens.Black,
new Rectangle((int)arrColumnLefts[iCount], iTopMargin,
(int)arrColumnWidths[iCount], iCellHeight));
iCount++;
}
}
iRow++;
iTopMargin += iCellHeight;
}
if (bMorePagesToPrint)
e.HasMorePages = true;
else
e.HasMorePages = false;
}
catch (Exception exc)
{
MessageBox.Show(exc.Message, "Error", MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
#endregion
-----------------------------------------------------------------------
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!