打印datagirdview
class DataGridViewPrinterusing System;using System.Text;using System.Collections;using System.Collections.Generic;using System.Drawing;using System.Drawing.Printing;using System.Data;using System.Windows.Forms;
class DataGridViewPrinter{
private DataGridView TheDataGridView; //The DataGridView Control which will be printed. private PrintDocument ThePrintDocument; //The PrintDocument to be used for printing. private bool IsCenterOnPage; //Determine if the report will be printed in the Top-Center of the page. private bool IsWithTitle; //Determine if the page contain title text. private string TheTitleText; //The title text to be printed in each page (if IsWithTitle is set to true) private Font TheTitleFont; //The font to be used with the title text (if IsWithTitle is set to true). private Color TheTitleColor; //The color to be used with the title text (if IsWithTitle is set to true).
private const int kCellLeeway = 10; //The constant cell spacing value.
static int CurrentRow; //A static parameter that keep track on which Row (in the DataGridView control) that should be printed.
private int PageWidth; private int PageHeight; private int LeftMargin; private int TopMargin; private int RightMargin; private int BottomMargin;
private int TheDataGridViewWidth; private int CurrentY; //A parameter that keep track on the y coordinate of the page, so the next object to be printed will start from this y coordinate.
//The class constructor. public DataGridViewPrinter(DataGridView aDataGridView, PrintDocument aPrintDocument, bool CenterOnPage, bool WithTitle, string aTitleText, Font aTitleFont, Color aTitleColor) { TheDataGridView = aDataGridView; ThePrintDocument = aPrintDocument; IsCenterOnPage = CenterOnPage; IsWithTitle = WithTitle; TheTitleText = aTitleText; TheTitleFont = aTitleFont; TheTitleColor = aTitleColor;
//Calculating TheDataGridViewWidth. TheDataGridViewWidth = 0; for (int i = 0; i < TheDataGridView.Columns.Count; i++) { //First, adjusting each column to be fit according the content of all its cells (including the header cell). TheDataGridView.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; //TheDataGridViewWidth is the sum of all visibled columns' width. if (TheDataGridView.Columns[i].Visible) TheDataGridViewWidth += (TheDataGridView.Columns[i].Width + kCellLeeway); }
//Claculating the PageWidth and the PageHeight. if (!ThePrintDocument.DefaultPageSettings.Landscape) { PageWidth = ThePrintDocument.DefaultPageSettings.PaperSize.Width; PageHeight = ThePrintDocument.DefaultPageSettings.PaperSize.Height; } else { PageHeight = ThePrintDocument.DefaultPageSettings.PaperSize.Width; PageWidth = ThePrintDocument.DefaultPageSettings.PaperSize.Height; }
//Claculating the page margins. LeftMargin = ThePrintDocument.DefaultPageSettings.Margins.Left; TopMargin = ThePrintDocument.DefaultPageSettings.Margins.Top; RightMargin = ThePrintDocument.DefaultPageSettings.Margins.Right; BottomMargin = ThePrintDocument.DefaultPageSettings.Margins.Bottom;
//First, the current row to be printed is the first row in the DataGridView control. CurrentRow = 0; }
//The funtion that print the title and the header row. private void DrawTitleAndHeader(Graphics g) { //Printing the title (if IsWithTitle is set to true). if (IsWithTitle) { StringFormat TitleFormat = new StringFormat(); TitleFormat.Trimming = StringTrimming.Word; TitleFormat.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.LineLimit | StringFormatFlags.NoClip; if (IsCenterOnPage) TitleFormat.Alignment = StringAlignment.Center; else TitleFormat.Alignment = StringAlignment.Near;
RectangleF TitleRectangle = new RectangleF((float)LeftMargin, (float)TopMargin, (float)PageWidth - (float)RightMargin - (float)LeftMargin, TheTitleFont.SizeInPoints + (float)kCellLeeway);
g.DrawString(TheTitleText, TheTitleFont, new SolidBrush(TheTitleColor), TitleRectangle, TitleFormat);
CurrentY = TopMargin + (int)TheTitleFont.SizeInPoints + 2 * kCellLeeway; } else CurrentY = TopMargin; //Because IsWithTitle is set to false then the printing will start from Top margin (y coordinate) of the page.
//Calculating the starting x coordinate that the printing process will start from. int CurrentX = LeftMargin; if (IsCenterOnPage) CurrentX += ((PageWidth - RightMargin - LeftMargin) - TheDataGridViewWidth) / 2;
//Setting the HeaderFore style. Color HeaderForeColor = TheDataGridView.RowHeadersDefaultCellStyle.ForeColor; if (HeaderForeColor.IsEmpty) //If there is no special HeaderFore style, then use the default DataGridView style. HeaderForeColor = TheDataGridView.DefaultCellStyle.ForeColor; SolidBrush HeaderForeBrush = new SolidBrush(HeaderForeColor);
//Setting the HeaderBack style. Color HeaderBackColor = TheDataGridView.RowHeadersDefaultCellStyle.BackColor; if (HeaderBackColor.IsEmpty) //If there is no special HeaderBack style, then use the default DataGridView style. HeaderBackColor = TheDataGridView.DefaultCellStyle.BackColor; SolidBrush HeaderBackBrush = new SolidBrush(HeaderBackColor);
//Setting the LinePen that will be used to draw lines and rectangles (derived from the GridColor property of the DataGridView control). Pen TheLinePen = new Pen(TheDataGridView.GridColor, 1);
//Setting the HeaderFont style. Font HeaderFont = TheDataGridView.RowHeadersDefaultCellStyle.Font; if (HeaderFont == null) //If there is no special HeaderFont style, then use the default DataGridView font style. HeaderFont = TheDataGridView.DefaultCellStyle.Font;
//Calculating and drawing the HeaderBounds. Rectangle HeaderBounds = new Rectangle(CurrentX, CurrentY, TheDataGridViewWidth, (int)HeaderFont.SizeInPoints + kCellLeeway); g.FillRectangle(HeaderBackBrush, HeaderBounds);
//Setting the format that will be used to print each cell of the header row. StringFormat CellFormat = new StringFormat(); CellFormat.Trimming = StringTrimming.Word; CellFormat.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.LineLimit | StringFormatFlags.NoClip;
//Printing each visible cell of the header row. RectangleF CellBounds; int ColumnWidth; for (int i = 0; i < TheDataGridView.Columns.Count; i++) { if (!TheDataGridView.Columns[i].Visible) continue; //If the column is not visible then ignore this iteration.
ColumnWidth = TheDataGridView.Columns[i].Width + kCellLeeway;
CellBounds = new RectangleF((float)CurrentX, (float)CurrentY, (float)ColumnWidth, HeaderFont.SizeInPoints + (float)kCellLeeway);
//Printing the cell text. g.DrawString(TheDataGridView.Columns[i].HeaderText, HeaderFont, HeaderForeBrush, CellBounds, CellFormat); //Drawing the cell bounds. if (TheDataGridView.RowHeadersBorderStyle != DataGridViewHeaderBorderStyle.None) //Draw the cell border only if the HeaderBorderStyle is not None. g.DrawRectangle(TheLinePen, (float)CurrentX, (float)CurrentY, (float)ColumnWidth, HeaderFont.SizeInPoints + (float)kCellLeeway);
CurrentX += ColumnWidth; }
CurrentY += (int)HeaderFont.SizeInPoints + kCellLeeway; }
//The function that print a bunch of rows that fit in one page. //When it returns true, meaning that there are more rows still not printed, so another PagePrint action is required, //when it returns false, meaning that all rows are printed (the CureentRow parameter reaches the last row of the DataGridView control) and no further PagePrint action is required. private bool DrawRows(Graphics g) { //Setting the LinePen that will be used to draw lines and rectangles (derived from the GridColor property of the DataGridView control). Pen TheLinePen = new Pen(TheDataGridView.GridColor, 1);
//The style paramters that will be used to print each cell. Font RowFont; Color RowForeColor; Color RowBackColor; SolidBrush RowForeBrush; SolidBrush RowBackBrush; SolidBrush RowAlternatingBackBrush;
//Setting the format that will be used to print each cell. StringFormat CellFormat = new StringFormat(); CellFormat.Trimming = StringTrimming.Word; CellFormat.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.LineLimit;
//Printing each visible cell RectangleF RowBounds; int CurrentX; int ColumnWidth; while (CurrentRow < TheDataGridView.Rows.Count) { if (TheDataGridView.Rows[CurrentRow].Visible) //Print the cells of the CurrentRow only if that row is visible. { //Setting the row font style. RowFont = TheDataGridView.Rows[CurrentRow].DefaultCellStyle.Font; if (RowFont == null) //If the there is no special font style of the CurrentRow, then use the default one associated with the DataGridView control. RowFont = TheDataGridView.DefaultCellStyle.Font;
//Setting the RowFore style. RowForeColor = TheDataGridView.Rows[CurrentRow].DefaultCellStyle.ForeColor; if (RowForeColor.IsEmpty) //If the there is no special RowFore style of the CurrentRow, then use the default one associated with the DataGridView control. RowForeColor = TheDataGridView.DefaultCellStyle.ForeColor; RowForeBrush = new SolidBrush(RowForeColor);
//Setting the RowBack (for even rows) and the RowAlternatingBack (for odd rows) styles. RowBackColor = TheDataGridView.Rows[CurrentRow].DefaultCellStyle.BackColor; if (RowBackColor.IsEmpty) //If the there is no special RowBack style of the CurrentRow, then use the default one associated with the DataGridView control. { RowBackBrush = new SolidBrush(TheDataGridView.DefaultCellStyle.BackColor); RowAlternatingBackBrush = new SolidBrush(TheDataGridView.AlternatingRowsDefaultCellStyle.BackColor); } else //If the there is a special RowBack style of the CurrentRow, then use it for both the RowBack and the RowAlternatingBack styles. { RowBackBrush = new SolidBrush(RowBackColor); RowAlternatingBackBrush = new SolidBrush(RowBackColor); }
//Calculating the starting x coordinate that the printing process will start from. CurrentX = LeftMargin; if (IsCenterOnPage) CurrentX += ((PageWidth - RightMargin - LeftMargin) - TheDataGridViewWidth) / 2;
//Calculating the entire CurrentRow bounds. RowBounds = new RectangleF((float)CurrentX, (float)CurrentY, (float)TheDataGridViewWidth, RowFont.SizeInPoints + (float)kCellLeeway);
//Filling the back of the CurrentRow. if (CurrentRow % 2 == 0) g.FillRectangle(RowBackBrush, RowBounds); else g.FillRectangle(RowAlternatingBackBrush, RowBounds);
//Printing each visible cell of the CurrentRow. for (int CurrentCell = 0; CurrentCell < TheDataGridView.Columns.Count; CurrentCell++) { if (!TheDataGridView.Columns[CurrentCell].Visible) continue; //If the cell is belong to invisible column, then ignore this iteration.
ColumnWidth = TheDataGridView.Columns[CurrentCell].Width + kCellLeeway; RectangleF CellBounds = new RectangleF((float)CurrentX, (float)CurrentY, (float)ColumnWidth, RowFont.SizeInPoints + (float)kCellLeeway);
//Printing the cell text. g.DrawString(TheDataGridView.Rows[CurrentRow].Cells[CurrentCell].Value.ToString(), RowFont, RowForeBrush, CellBounds, CellFormat); //Drawing the cell bounds. if (TheDataGridView.CellBorderStyle != DataGridViewCellBorderStyle.None) //Draw the cell border only if the CellBorderStyle is not None. g.DrawRectangle(TheLinePen, (float)CurrentX, (float)CurrentY, (float)ColumnWidth, RowFont.SizeInPoints + (float)kCellLeeway);
CurrentX += ColumnWidth; } CurrentY += (int)RowFont.SizeInPoints + kCellLeeway;
//Checking if the CurrentY is exceeds the page boundries, //if so then exit the function and returning true meaning another PagePrint action is required. if (CurrentY > (PageHeight - TopMargin - BottomMargin)) { CurrentRow++; return true; } } CurrentRow++; } //If the while loop ends meaning that the CurrentRow reaches the last row of the DataGridView control. //So, the function will return false meaning that no further PagePrint action is required, //but if the PagePrint action is fired again then the printing will start over from the first row, //that's why the CurrentRow is set to zero before returning false. CurrentRow = 0; return false; }
//The method that calls the functions that print the Title (if IsWithTitle is set to true), header row, and bunch of rows that fit in one page. public bool DrawDataGridView(Graphics g) { try { DrawTitleAndHeader(g); bool bContinue = DrawRows(g); return bContinue; } catch (Exception ex) { MessageBox.Show("Operation failed: " + ex.Message.ToString(), Application.ProductName + " - Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; }
}}