using
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;
public class DataGridViewPrinter
... {
/**//// <summary>
/// The DataGridView Control which will be printed
/// </summary>
private DataGridView TheDataGridView;
/**//// <summary>
/// The PrintDocument to be used for printing
/// </summary>
private PrintDocument ThePrintDocument;
/**//// <summary>
/// Determine if the report will be printed in the Top-Center of the page
/// </summary>
private bool IsCenterOnPage;
/**//// <summary>
/// Determine if the page contain title text
/// </summary>
private bool IsWithTitle;
/**//// <summary>
/// The title text to be printed in each page (if IsWithTitle is set to true)
/// </summary>
private string TheTitleText;
/**//// <summary>
/// The font to be used with the title text (if IsWithTitle is set to true)
/// </summary>
private Font TheTitleFont;
/**//// <summary>
/// The color to be used with the title text (if IsWithTitle is set to true)
/// </summary>
private Color TheTitleColor;
/**//// <summary>
/// Determine if paging is used
/// </summary>
private bool IsWithPaging;
/**//// <summary>
/// To indicate whether the DataGridView print Fit to Page
/// </summary>
/// <remarks>if it's not set, default True</remarks>
private bool fitToPage;
/**//// <summary>
/// A static parameter that keep track on which Row (in the DataGridView control) that should be printed
/// </summary>
static int CurrentRow;
/**//// <summary>
/// A static parameter that representing the pages
/// </summary>
static int PageNumber;
private int PageWidth;
private int PageHeight;
private int LeftMargin;
private int TopMargin;
private int RightMargin;
private int BottomMargin;
/**//// <summary>
/// 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
/// </summary>
private float CurrentY;
private float RowHeaderHeight;
private List<float> RowsHeight;
private List<float> ColumnsWidth;
private float TheDataGridViewWidth;
/**//// <summary>
/// Maintain a generic list to hold start/stop points for the column printing
/// This will be used for wrapping in situations where the DataGridView will not fit on a single page
/// </summary>
private List<int[]> mColumnPoints;
private List<float> mColumnPointsWidth;
private int mColumnPoint;
/**//// <summary>
/// A parameter to indicate Font Scale ratio
/// </summary>
private float mRatio = 1.0f;
/**//// <summary>
/// A parameter to indicate the Print Margin
/// </summary>
private const int mMARGIN = 40;
/**//// <summary>
/// The printer's constructor
/// </summary>
/// <param name="aDataGridView">A DataGridView will be printed</param>
/// <param name="aPrintDocument">A printDocument to be used for printing</param>
/// <param name="CenterOnPage">A variable representing print the report in the center or not</param>
/// <param name="WithTitle">A variable representing print the report title or not</param>
/// <param name="aTitleText">A variable representing the report's title</param>
/// <param name="aTitleFont">A variable representing the title's font of the report</param>
/// <param name="aTitleColor">A variable representing the title's color of the report</param>
/// <param name="WithPaging">A variable representing the paging is used or not</param>
public DataGridViewPrinter(DataGridView aDataGridView, PrintDocument aPrintDocument,
bool CenterOnPage, bool WithTitle, string aTitleText, Font aTitleFont, Color aTitleColor, bool WithPaging)
...{
TheDataGridView = aDataGridView;
ThePrintDocument = aPrintDocument;
IsCenterOnPage = CenterOnPage;
IsWithTitle = WithTitle;
TheTitleText = aTitleText;
TheTitleFont = aTitleFont;
TheTitleColor = aTitleColor;
IsWithPaging = WithPaging;
PageNumber = 0;
RowsHeight = new List<float>();
ColumnsWidth = new List<float>();
mColumnPoints = new List<int[]>();
mColumnPointsWidth = new List<float>();
fitToPage = true;
// 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;
}
/**//// <summary>
/// An overload constructor
/// </summary>
/// <param name="aDataGridView">A DataGridView will be printed</param>
/// <param name="CenterOnPage">A variable representing print the report in the center or not</param>
/// <param name="WithTitle">A variable representing print the report title or not</param>
/// <param name="aTitleText">A variable representing the report's title</param>
/// <param name="aTitleFont">A variable representing the title's font of the report</param>
/// <param name="aTitleColor">A variable representing the title's color of the report</param>
/// <param name="WithPaging">A variable representing the paging is used or not</param>
public DataGridViewPrinter(DataGridView aDataGridView, bool CenterOnPage, bool WithTitle,
string aTitleText, Font aTitleFont, Color aTitleColor, bool WithPaging)
...{
ThePrintDocument = new PrintDocument();
ThePrintDocument.PrintPage += new PrintPageEventHandler(PrintDocument_PrintPage);
PrintDialog MyPrintDialog = new PrintDialog();
MyPrintDialog.AllowCurrentPage = false;
MyPrintDialog.AllowPrintToFile = false;
MyPrintDialog.AllowSelection = false;
MyPrintDialog.AllowSomePages = false;
MyPrintDialog.PrintToFile = false;
MyPrintDialog.ShowHelp = false;
MyPrintDialog.ShowNetwork = false;
if (MyPrintDialog.ShowDialog() == DialogResult.OK)
...{
ThePrintDocument.DocumentName = aTitleText;
ThePrintDocument.PrinterSettings = MyPrintDialog.PrinterSettings;
ThePrintDocument.DefaultPageSettings = MyPrintDialog.PrinterSettings.DefaultPageSettings;
ThePrintDocument.DefaultPageSettings.Margins = new Margins(mMARGIN, mMARGIN, mMARGIN, mMARGIN);
TheDataGridView = aDataGridView;
IsCenterOnPage = CenterOnPage;
IsWithTitle = WithTitle;
TheTitleText = aTitleText;
TheTitleFont = aTitleFont;
TheTitleColor = aTitleColor;
IsWithPaging = WithPaging;
PageNumber = 0;
RowsHeight = new List<float>();
ColumnsWidth = new List<float>();
mColumnPoints = new List<int[]>();
mColumnPointsWidth = new List<float>();
fitToPage = true;
// 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;
PrintPreviewDialog printPreviewDialog = new PrintPreviewDialog();
printPreviewDialog.Document = ThePrintDocument;
printPreviewDialog.ShowIcon = false;
printPreviewDialog.Text = aTitleText + " Print Preview";
printPreviewDialog.ShowDialog();
}
}
/**//// <summary>
/// An overload constructor
/// </summary>
/// <param name="aDataGridView">A DataGridView will be printed</param>
/// <param name="CenterOnPage">A variable representing print the report in the center or not</param>
/// <param name="WithTitle">A variable representing print the report title or not</param>
/// <param name="aTitleText">A variable representing the report's title</param>
/// <param name="aTitleFont">A variable representing the title's font of the report</param>
/// <param name="aTitleColor">A variable representing the title's color of the report</param>
/// <param name="WithPaging">A variable representing the paging is used or not</param>
/// <param name="FitToPage">A variable representing the printing DataGridView fit to page or not</param>
public DataGridViewPrinter(DataGridView aDataGridView, bool CenterOnPage, bool WithTitle,
string aTitleText, Font aTitleFont, Color aTitleColor, bool WithPaging, bool FitToPage)
...{
ThePrintDocument = new PrintDocument();
ThePrintDocument.PrintPage += new PrintPageEventHandler(PrintDocument_PrintPage);
PrintDialog MyPrintDialog = new PrintDialog();
MyPrintDialog.AllowCurrentPage = false;
MyPrintDialog.AllowPrintToFile = false;
MyPrintDialog.AllowSelection = false;
MyPrintDialog.AllowSomePages = false;
MyPrintDialog.PrintToFile = false;
MyPrintDialog.ShowHelp = false;
MyPrintDialog.ShowNetwork = false;
if (MyPrintDialog.ShowDialog() == DialogResult.OK)
...{
ThePrintDocument.DocumentName = aTitleText;
ThePrintDocument.PrinterSettings = MyPrintDialog.PrinterSettings;
ThePrintDocument.DefaultPageSettings = MyPrintDialog.PrinterSettings.DefaultPageSettings;
ThePrintDocument.DefaultPageSettings.Margins = new Margins(mMARGIN, mMARGIN, mMARGIN, mMARGIN);
TheDataGridView = aDataGridView;
IsCenterOnPage = CenterOnPage;
IsWithTitle = WithTitle;
TheTitleText = aTitleText;
TheTitleFont = aTitleFont;
TheTitleColor = aTitleColor;
IsWithPaging = WithPaging;
PageNumber = 0;
RowsHeight = new List<float>();
ColumnsWidth = new List<float>();
mColumnPoints = new List<int[]>();
mColumnPointsWidth = new List<float>();
fitToPage = FitToPage;
// 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;
PrintPreviewDialog printPreviewDialog = new PrintPreviewDialog();
printPreviewDialog.Document = ThePrintDocument;
printPreviewDialog.ShowIcon = false;
printPreviewDialog.Text = aTitleText + " Print Preview";
printPreviewDialog.ShowDialog();
}
}
/**//// <summary>
/// A PrintPageEventHandler
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void PrintDocument_PrintPage(object sender, PrintPageEventArgs e)
...{
bool more = this.DrawDataGridView(e.Graphics);
if (more)
...{
e.HasMorePages = true;
}
}
/**//// <summary>
/// The function that calculate the height of each row (including the header row)
/// the width of each column (according to the longest text in all its cells including the header cell)
/// and the whole DataGridView width
/// </summary>
/// <param name="g"></param>
private void Calculate(Graphics g)
...{
// Just calculate once
if (PageNumber == 0)
...{
SizeF tmpSize = new SizeF();
Font tmpFont;
float tmpWidth;
float mTempPrintArea = (float)PageWidth - (float)LeftMargin - (float)RightMargin;
TheDataGridViewWidth = 0;
for (int i = 0; i < TheDataGridView.Columns.Count; i++)
...{
tmpFont = TheDataGridView.ColumnHeadersDefaultCellStyle.Font;
/**//*If there is no special HeaderFont style
* then use the default DataGridView font style
*/
if (tmpFont == null)
tmpFont = TheDataGridView.DefaultCellStyle.Font;
tmpSize = g.MeasureString(TheDataGridView.Columns[i].HeaderText, tmpFont);
tmpWidth = tmpSize.Width;
RowHeaderHeight = tmpSize.Height;
for (int j = 0; j < TheDataGridView.Rows.Count; j++)
...{
tmpFont = TheDataGridView.Rows[j].DefaultCellStyle.Font;
/**//*If the there is no special font style of the CurrentRow
* then use the default one associated with the DataGridView control
*/
if (tmpFont == null)
tmpFont = TheDataGridView.DefaultCellStyle.Font;
tmpSize = g.MeasureString("Anything", tmpFont);
RowsHeight.Add(tmpSize.Height);
tmpSize = g.MeasureString(TheDataGridView.Rows[j].Cells[i].EditedFormattedValue.ToString(), tmpFont);
if (tmpSize.Width > tmpWidth)
tmpWidth = tmpSize.Width;
}
if (TheDataGridView.Columns[i].Visible)
TheDataGridViewWidth += tmpWidth;
ColumnsWidth.Add(tmpWidth);
}
if (TheDataGridViewWidth > mTempPrintArea && fitToPage)
...{
float extra = TheDataGridViewWidth - mTempPrintArea;
mRatio = 1 - extra / TheDataGridViewWidth;
RowHeaderHeight *= mRatio;
for (int i = 0; i < RowsHeight.Count; i++)
...{
RowsHeight[i] *= mRatio;
}
for (int i = 0; i < ColumnsWidth.Count; i++)
...{
ColumnsWidth[i] *= mRatio;
}
TheDataGridViewWidth *= mRatio;
}
/**//* Define the start/stop column points based on the page width and the DataGridView Width
* We will use this to determine the columns which are drawn on each page and how wrapping will be handled
* By default, the wrapping will occurr such that the maximum number of columns for a page will be determine
*/
int k;
int mStartPoint = 0;
for (k = 0; k < TheDataGridView.Columns.Count; k++)
if (TheDataGridView.Columns[k].Visible)
...{
mStartPoint = k;
break;
}
int mEndPoint = TheDataGridView.Columns.Count;
for (k = TheDataGridView.Columns.Count - 1; k >= 0; k--)
if (TheDataGridView.Columns[k].Visible)
...{
mEndPoint = k + 1;
break;
}
float mTempWidth = TheDataGridViewWidth;
// We only care about handling where the total datagridview width is bigger than the print area
if (!fitToPage)
...{
if (TheDataGridViewWidth > mTempPrintArea)
...{
mTempWidth = 0.0F;
for (k = 0; k < TheDataGridView.Columns.Count; k++)
...{
if (TheDataGridView.Columns[k].Visible)
...{
mTempWidth += ColumnsWidth[k];
/**//* If the width is bigger than the page area
* then define a new column print range
*/
if (mTempWidth > mTempPrintArea)
...{
mTempWidth -= ColumnsWidth[k];
mColumnPoints.Add(new int[] ...{ mStartPoint, mEndPoint });
mColumnPointsWidth.Add(mTempWidth);
mStartPoint = k;
mTempWidth = ColumnsWidth[k];
}
}
// Our end point is actually one index above the current index
mEndPoint = k + 1;
}
}
}
// Add the last set of columns
mColumnPoints.Add(new int[] ...{ mStartPoint, mEndPoint });
mColumnPointsWidth.Add(mTempWidth);
mColumnPoint = 0;
}
}
/**//// <summary>
/// The funtion that print the title, page number, and the header row
/// </summary>
/// <param name="g"></param>
private void DrawHeader(Graphics g)
...{
CurrentY = (float)TopMargin;
// Printing the page number (if isWithPaging is set to true)
if (IsWithPaging)
...{
PageNumber++;
string PageString = "Page " + PageNumber.ToString();
StringFormat PageStringFormat = new StringFormat();
PageStringFormat.Trimming = StringTrimming.Word;
PageStringFormat.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.LineLimit | StringFormatFlags.NoClip;
PageStringFormat.Alignment = StringAlignment.Far;
Font PageStringFont = new Font("Tahoma", 8, FontStyle.Regular, GraphicsUnit.Point);
RectangleF PageStringRectangle = new RectangleF((float)LeftMargin, CurrentY, (float)PageWidth - (float)RightMargin - (float)LeftMargin, g.MeasureString(PageString, PageStringFont).Height);
g.DrawString(PageString, PageStringFont, new SolidBrush(Color.Black), PageStringRectangle, PageStringFormat);
CurrentY += g.MeasureString(PageString, PageStringFont).Height;
}
// 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, CurrentY, (float)PageWidth - (float)RightMargin - (float)LeftMargin, g.MeasureString(TheTitleText, TheTitleFont).Height);
g.DrawString(TheTitleText, TheTitleFont, new SolidBrush(TheTitleColor), TitleRectangle, TitleFormat);
CurrentY += g.MeasureString(TheTitleText, TheTitleFont).Height;
}
// Calculating the starting x coordinate that the printing process will start from
float CurrentX = (float)LeftMargin;
if (IsCenterOnPage)
CurrentX += (((float)PageWidth - (float)RightMargin - (float)LeftMargin) - mColumnPointsWidth[mColumnPoint]) / 2.0F;
// Setting the HeaderFore style
Color HeaderForeColor = TheDataGridView.ColumnHeadersDefaultCellStyle.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.ColumnHeadersDefaultCellStyle.BackColor;
// If there is no special HeaderBack style, then use the default DataGridView style
if (HeaderBackColor.IsEmpty)
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.ColumnHeadersDefaultCellStyle.Font;
//if (HeaderFont == null) // If there is no special HeaderFont style, then use the default DataGridView font style
// HeaderFont = TheDataGridView.DefaultCellStyle.Font;
Font HeaderFont = null;
if (TheDataGridView.ColumnHeadersDefaultCellStyle.Font != null)
...{
HeaderFont = new Font(TheDataGridView.ColumnHeadersDefaultCellStyle.Font.FontFamily,
TheDataGridView.ColumnHeadersDefaultCellStyle.Font.Size * mRatio);
}
if (HeaderFont == null)
...{
HeaderFont = new Font(TheDataGridView.DefaultCellStyle.Font.FontFamily,
TheDataGridView.DefaultCellStyle.Font.Size * mRatio);
}
// Calculating and drawing the HeaderBounds
RectangleF HeaderBounds = new RectangleF(CurrentX, CurrentY, mColumnPointsWidth[mColumnPoint], RowHeaderHeight);
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;
float ColumnWidth;
for (int i = (int)mColumnPoints[mColumnPoint].GetValue(0); i < (int)mColumnPoints[mColumnPoint].GetValue(1); i++)
...{
if (!TheDataGridView.Columns[i].Visible) continue; // If the column is not visible then ignore this iteration
ColumnWidth = ColumnsWidth[i];
// Check the CurrentCell alignment and apply it to the CellFormat
if (TheDataGridView.ColumnHeadersDefaultCellStyle.Alignment.ToString().Contains("Right"))
CellFormat.Alignment = StringAlignment.Far;
else if (TheDataGridView.ColumnHeadersDefaultCellStyle.Alignment.ToString().Contains("Center"))
CellFormat.Alignment = StringAlignment.Center;
else
CellFormat.Alignment = StringAlignment.Near;
CellBounds = new RectangleF(CurrentX, CurrentY, ColumnWidth, RowHeaderHeight);
// 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, CurrentX, CurrentY, ColumnWidth, RowHeaderHeight);
CurrentX += ColumnWidth;
}
CurrentY += RowHeaderHeight;
}
/**//// <summary>
/// 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
/// </summary>
/// <param name="g"></param>
/// <returns>bool</returns>
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 = null;
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;
float CurrentX;
float ColumnWidth;
while (CurrentRow < TheDataGridView.Rows.Count)
...{
// Print the cells of the CurrentRow only if that row is visible
if (TheDataGridView.Rows[CurrentRow].Visible)
...{
// Setting the row font style
//RowFont = TheDataGridView.Rows[CurrentRow].DefaultCellStyle.Font;
if (TheDataGridView.Rows[CurrentRow].DefaultCellStyle.Font != null)
...{
RowFont = new Font(TheDataGridView.Rows[CurrentRow].DefaultCellStyle.Font.FontFamily,
TheDataGridView.Rows[CurrentRow].DefaultCellStyle.Font.Size * mRatio);
}
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;
RowFont = new Font(TheDataGridView.DefaultCellStyle.Font.FontFamily,
TheDataGridView.DefaultCellStyle.Font.Size * mRatio);
// 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 the there is no special RowBack style of the CurrentRow
* then use the default one associated with the DataGridView control
*/
if (RowBackColor.IsEmpty)
...{
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 = (float)LeftMargin;
if (IsCenterOnPage)
CurrentX += (((float)PageWidth - (float)RightMargin - (float)LeftMargin) - mColumnPointsWidth[mColumnPoint]) / 2.0F;
// Calculating the entire CurrentRow bounds
RowBounds = new RectangleF(CurrentX, CurrentY, mColumnPointsWidth[mColumnPoint], RowsHeight[CurrentRow]);
// 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 = (int)mColumnPoints[mColumnPoint].GetValue(0); CurrentCell < (int)mColumnPoints[mColumnPoint].GetValue(1); CurrentCell++)
...{
if (!TheDataGridView.Columns[CurrentCell].Visible) continue; // If the cell is belong to invisible column, then ignore this iteration
// Check the CurrentCell alignment and apply it to the CellFormat
if (TheDataGridView.Columns[CurrentCell].DefaultCellStyle.Alignment.ToString().Contains("Right"))
CellFormat.Alignment = StringAlignment.Far;
else if (TheDataGridView.Columns[CurrentCell].DefaultCellStyle.Alignment.ToString().Contains("Center"))
CellFormat.Alignment = StringAlignment.Center;
else
CellFormat.Alignment = StringAlignment.Near;
ColumnWidth = ColumnsWidth[CurrentCell];
RectangleF CellBounds = new RectangleF(CurrentX, CurrentY, ColumnWidth, RowsHeight[CurrentRow]);
// Printing the cell text
g.DrawString(TheDataGridView.Rows[CurrentRow].Cells[CurrentCell].EditedFormattedValue.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, CurrentX, CurrentY, ColumnWidth, RowsHeight[CurrentRow]);
CurrentX += ColumnWidth;
}
CurrentY += RowsHeight[CurrentRow];
/**//* 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 ((int)CurrentY > (PageHeight - TopMargin - BottomMargin))
...{
CurrentRow++;
return true;
}
}
CurrentRow++;
}
CurrentRow = 0;
// Continue to print the next group of columns
mColumnPoint++;
// Which means all columns are printed
if (mColumnPoint == mColumnPoints.Count)
...{
mColumnPoint = 0;
return false;
}
else
return true;
}
/**//// <summary>
/// The method that calls all other functions
/// </summary>
/// <param name="g"></param>
/// <returns>bool</returns>
public bool DrawDataGridView(Graphics g)
...{
try
...{
Calculate(g);
DrawHeader(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;
}
}
}
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Printing;
using System.Data;
using System.Windows.Forms;
public class DataGridViewPrinter
... {
/**//// <summary>
/// The DataGridView Control which will be printed
/// </summary>
private DataGridView TheDataGridView;
/**//// <summary>
/// The PrintDocument to be used for printing
/// </summary>
private PrintDocument ThePrintDocument;
/**//// <summary>
/// Determine if the report will be printed in the Top-Center of the page
/// </summary>
private bool IsCenterOnPage;
/**//// <summary>
/// Determine if the page contain title text
/// </summary>
private bool IsWithTitle;
/**//// <summary>
/// The title text to be printed in each page (if IsWithTitle is set to true)
/// </summary>
private string TheTitleText;
/**//// <summary>
/// The font to be used with the title text (if IsWithTitle is set to true)
/// </summary>
private Font TheTitleFont;
/**//// <summary>
/// The color to be used with the title text (if IsWithTitle is set to true)
/// </summary>
private Color TheTitleColor;
/**//// <summary>
/// Determine if paging is used
/// </summary>
private bool IsWithPaging;
/**//// <summary>
/// To indicate whether the DataGridView print Fit to Page
/// </summary>
/// <remarks>if it's not set, default True</remarks>
private bool fitToPage;
/**//// <summary>
/// A static parameter that keep track on which Row (in the DataGridView control) that should be printed
/// </summary>
static int CurrentRow;
/**//// <summary>
/// A static parameter that representing the pages
/// </summary>
static int PageNumber;
private int PageWidth;
private int PageHeight;
private int LeftMargin;
private int TopMargin;
private int RightMargin;
private int BottomMargin;
/**//// <summary>
/// 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
/// </summary>
private float CurrentY;
private float RowHeaderHeight;
private List<float> RowsHeight;
private List<float> ColumnsWidth;
private float TheDataGridViewWidth;
/**//// <summary>
/// Maintain a generic list to hold start/stop points for the column printing
/// This will be used for wrapping in situations where the DataGridView will not fit on a single page
/// </summary>
private List<int[]> mColumnPoints;
private List<float> mColumnPointsWidth;
private int mColumnPoint;
/**//// <summary>
/// A parameter to indicate Font Scale ratio
/// </summary>
private float mRatio = 1.0f;
/**//// <summary>
/// A parameter to indicate the Print Margin
/// </summary>
private const int mMARGIN = 40;
/**//// <summary>
/// The printer's constructor
/// </summary>
/// <param name="aDataGridView">A DataGridView will be printed</param>
/// <param name="aPrintDocument">A printDocument to be used for printing</param>
/// <param name="CenterOnPage">A variable representing print the report in the center or not</param>
/// <param name="WithTitle">A variable representing print the report title or not</param>
/// <param name="aTitleText">A variable representing the report's title</param>
/// <param name="aTitleFont">A variable representing the title's font of the report</param>
/// <param name="aTitleColor">A variable representing the title's color of the report</param>
/// <param name="WithPaging">A variable representing the paging is used or not</param>
public DataGridViewPrinter(DataGridView aDataGridView, PrintDocument aPrintDocument,
bool CenterOnPage, bool WithTitle, string aTitleText, Font aTitleFont, Color aTitleColor, bool WithPaging)
...{
TheDataGridView = aDataGridView;
ThePrintDocument = aPrintDocument;
IsCenterOnPage = CenterOnPage;
IsWithTitle = WithTitle;
TheTitleText = aTitleText;
TheTitleFont = aTitleFont;
TheTitleColor = aTitleColor;
IsWithPaging = WithPaging;
PageNumber = 0;
RowsHeight = new List<float>();
ColumnsWidth = new List<float>();
mColumnPoints = new List<int[]>();
mColumnPointsWidth = new List<float>();
fitToPage = true;
// 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;
}
/**//// <summary>
/// An overload constructor
/// </summary>
/// <param name="aDataGridView">A DataGridView will be printed</param>
/// <param name="CenterOnPage">A variable representing print the report in the center or not</param>
/// <param name="WithTitle">A variable representing print the report title or not</param>
/// <param name="aTitleText">A variable representing the report's title</param>
/// <param name="aTitleFont">A variable representing the title's font of the report</param>
/// <param name="aTitleColor">A variable representing the title's color of the report</param>
/// <param name="WithPaging">A variable representing the paging is used or not</param>
public DataGridViewPrinter(DataGridView aDataGridView, bool CenterOnPage, bool WithTitle,
string aTitleText, Font aTitleFont, Color aTitleColor, bool WithPaging)
...{
ThePrintDocument = new PrintDocument();
ThePrintDocument.PrintPage += new PrintPageEventHandler(PrintDocument_PrintPage);
PrintDialog MyPrintDialog = new PrintDialog();
MyPrintDialog.AllowCurrentPage = false;
MyPrintDialog.AllowPrintToFile = false;
MyPrintDialog.AllowSelection = false;
MyPrintDialog.AllowSomePages = false;
MyPrintDialog.PrintToFile = false;
MyPrintDialog.ShowHelp = false;
MyPrintDialog.ShowNetwork = false;
if (MyPrintDialog.ShowDialog() == DialogResult.OK)
...{
ThePrintDocument.DocumentName = aTitleText;
ThePrintDocument.PrinterSettings = MyPrintDialog.PrinterSettings;
ThePrintDocument.DefaultPageSettings = MyPrintDialog.PrinterSettings.DefaultPageSettings;
ThePrintDocument.DefaultPageSettings.Margins = new Margins(mMARGIN, mMARGIN, mMARGIN, mMARGIN);
TheDataGridView = aDataGridView;
IsCenterOnPage = CenterOnPage;
IsWithTitle = WithTitle;
TheTitleText = aTitleText;
TheTitleFont = aTitleFont;
TheTitleColor = aTitleColor;
IsWithPaging = WithPaging;
PageNumber = 0;
RowsHeight = new List<float>();
ColumnsWidth = new List<float>();
mColumnPoints = new List<int[]>();
mColumnPointsWidth = new List<float>();
fitToPage = true;
// 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;
PrintPreviewDialog printPreviewDialog = new PrintPreviewDialog();
printPreviewDialog.Document = ThePrintDocument;
printPreviewDialog.ShowIcon = false;
printPreviewDialog.Text = aTitleText + " Print Preview";
printPreviewDialog.ShowDialog();
}
}
/**//// <summary>
/// An overload constructor
/// </summary>
/// <param name="aDataGridView">A DataGridView will be printed</param>
/// <param name="CenterOnPage">A variable representing print the report in the center or not</param>
/// <param name="WithTitle">A variable representing print the report title or not</param>
/// <param name="aTitleText">A variable representing the report's title</param>
/// <param name="aTitleFont">A variable representing the title's font of the report</param>
/// <param name="aTitleColor">A variable representing the title's color of the report</param>
/// <param name="WithPaging">A variable representing the paging is used or not</param>
/// <param name="FitToPage">A variable representing the printing DataGridView fit to page or not</param>
public DataGridViewPrinter(DataGridView aDataGridView, bool CenterOnPage, bool WithTitle,
string aTitleText, Font aTitleFont, Color aTitleColor, bool WithPaging, bool FitToPage)
...{
ThePrintDocument = new PrintDocument();
ThePrintDocument.PrintPage += new PrintPageEventHandler(PrintDocument_PrintPage);
PrintDialog MyPrintDialog = new PrintDialog();
MyPrintDialog.AllowCurrentPage = false;
MyPrintDialog.AllowPrintToFile = false;
MyPrintDialog.AllowSelection = false;
MyPrintDialog.AllowSomePages = false;
MyPrintDialog.PrintToFile = false;
MyPrintDialog.ShowHelp = false;
MyPrintDialog.ShowNetwork = false;
if (MyPrintDialog.ShowDialog() == DialogResult.OK)
...{
ThePrintDocument.DocumentName = aTitleText;
ThePrintDocument.PrinterSettings = MyPrintDialog.PrinterSettings;
ThePrintDocument.DefaultPageSettings = MyPrintDialog.PrinterSettings.DefaultPageSettings;
ThePrintDocument.DefaultPageSettings.Margins = new Margins(mMARGIN, mMARGIN, mMARGIN, mMARGIN);
TheDataGridView = aDataGridView;
IsCenterOnPage = CenterOnPage;
IsWithTitle = WithTitle;
TheTitleText = aTitleText;
TheTitleFont = aTitleFont;
TheTitleColor = aTitleColor;
IsWithPaging = WithPaging;
PageNumber = 0;
RowsHeight = new List<float>();
ColumnsWidth = new List<float>();
mColumnPoints = new List<int[]>();
mColumnPointsWidth = new List<float>();
fitToPage = FitToPage;
// 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;
PrintPreviewDialog printPreviewDialog = new PrintPreviewDialog();
printPreviewDialog.Document = ThePrintDocument;
printPreviewDialog.ShowIcon = false;
printPreviewDialog.Text = aTitleText + " Print Preview";
printPreviewDialog.ShowDialog();
}
}
/**//// <summary>
/// A PrintPageEventHandler
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void PrintDocument_PrintPage(object sender, PrintPageEventArgs e)
...{
bool more = this.DrawDataGridView(e.Graphics);
if (more)
...{
e.HasMorePages = true;
}
}
/**//// <summary>
/// The function that calculate the height of each row (including the header row)
/// the width of each column (according to the longest text in all its cells including the header cell)
/// and the whole DataGridView width
/// </summary>
/// <param name="g"></param>
private void Calculate(Graphics g)
...{
// Just calculate once
if (PageNumber == 0)
...{
SizeF tmpSize = new SizeF();
Font tmpFont;
float tmpWidth;
float mTempPrintArea = (float)PageWidth - (float)LeftMargin - (float)RightMargin;
TheDataGridViewWidth = 0;
for (int i = 0; i < TheDataGridView.Columns.Count; i++)
...{
tmpFont = TheDataGridView.ColumnHeadersDefaultCellStyle.Font;
/**//*If there is no special HeaderFont style
* then use the default DataGridView font style
*/
if (tmpFont == null)
tmpFont = TheDataGridView.DefaultCellStyle.Font;
tmpSize = g.MeasureString(TheDataGridView.Columns[i].HeaderText, tmpFont);
tmpWidth = tmpSize.Width;
RowHeaderHeight = tmpSize.Height;
for (int j = 0; j < TheDataGridView.Rows.Count; j++)
...{
tmpFont = TheDataGridView.Rows[j].DefaultCellStyle.Font;
/**//*If the there is no special font style of the CurrentRow
* then use the default one associated with the DataGridView control
*/
if (tmpFont == null)
tmpFont = TheDataGridView.DefaultCellStyle.Font;
tmpSize = g.MeasureString("Anything", tmpFont);
RowsHeight.Add(tmpSize.Height);
tmpSize = g.MeasureString(TheDataGridView.Rows[j].Cells[i].EditedFormattedValue.ToString(), tmpFont);
if (tmpSize.Width > tmpWidth)
tmpWidth = tmpSize.Width;
}
if (TheDataGridView.Columns[i].Visible)
TheDataGridViewWidth += tmpWidth;
ColumnsWidth.Add(tmpWidth);
}
if (TheDataGridViewWidth > mTempPrintArea && fitToPage)
...{
float extra = TheDataGridViewWidth - mTempPrintArea;
mRatio = 1 - extra / TheDataGridViewWidth;
RowHeaderHeight *= mRatio;
for (int i = 0; i < RowsHeight.Count; i++)
...{
RowsHeight[i] *= mRatio;
}
for (int i = 0; i < ColumnsWidth.Count; i++)
...{
ColumnsWidth[i] *= mRatio;
}
TheDataGridViewWidth *= mRatio;
}
/**//* Define the start/stop column points based on the page width and the DataGridView Width
* We will use this to determine the columns which are drawn on each page and how wrapping will be handled
* By default, the wrapping will occurr such that the maximum number of columns for a page will be determine
*/
int k;
int mStartPoint = 0;
for (k = 0; k < TheDataGridView.Columns.Count; k++)
if (TheDataGridView.Columns[k].Visible)
...{
mStartPoint = k;
break;
}
int mEndPoint = TheDataGridView.Columns.Count;
for (k = TheDataGridView.Columns.Count - 1; k >= 0; k--)
if (TheDataGridView.Columns[k].Visible)
...{
mEndPoint = k + 1;
break;
}
float mTempWidth = TheDataGridViewWidth;
// We only care about handling where the total datagridview width is bigger than the print area
if (!fitToPage)
...{
if (TheDataGridViewWidth > mTempPrintArea)
...{
mTempWidth = 0.0F;
for (k = 0; k < TheDataGridView.Columns.Count; k++)
...{
if (TheDataGridView.Columns[k].Visible)
...{
mTempWidth += ColumnsWidth[k];
/**//* If the width is bigger than the page area
* then define a new column print range
*/
if (mTempWidth > mTempPrintArea)
...{
mTempWidth -= ColumnsWidth[k];
mColumnPoints.Add(new int[] ...{ mStartPoint, mEndPoint });
mColumnPointsWidth.Add(mTempWidth);
mStartPoint = k;
mTempWidth = ColumnsWidth[k];
}
}
// Our end point is actually one index above the current index
mEndPoint = k + 1;
}
}
}
// Add the last set of columns
mColumnPoints.Add(new int[] ...{ mStartPoint, mEndPoint });
mColumnPointsWidth.Add(mTempWidth);
mColumnPoint = 0;
}
}
/**//// <summary>
/// The funtion that print the title, page number, and the header row
/// </summary>
/// <param name="g"></param>
private void DrawHeader(Graphics g)
...{
CurrentY = (float)TopMargin;
// Printing the page number (if isWithPaging is set to true)
if (IsWithPaging)
...{
PageNumber++;
string PageString = "Page " + PageNumber.ToString();
StringFormat PageStringFormat = new StringFormat();
PageStringFormat.Trimming = StringTrimming.Word;
PageStringFormat.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.LineLimit | StringFormatFlags.NoClip;
PageStringFormat.Alignment = StringAlignment.Far;
Font PageStringFont = new Font("Tahoma", 8, FontStyle.Regular, GraphicsUnit.Point);
RectangleF PageStringRectangle = new RectangleF((float)LeftMargin, CurrentY, (float)PageWidth - (float)RightMargin - (float)LeftMargin, g.MeasureString(PageString, PageStringFont).Height);
g.DrawString(PageString, PageStringFont, new SolidBrush(Color.Black), PageStringRectangle, PageStringFormat);
CurrentY += g.MeasureString(PageString, PageStringFont).Height;
}
// 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, CurrentY, (float)PageWidth - (float)RightMargin - (float)LeftMargin, g.MeasureString(TheTitleText, TheTitleFont).Height);
g.DrawString(TheTitleText, TheTitleFont, new SolidBrush(TheTitleColor), TitleRectangle, TitleFormat);
CurrentY += g.MeasureString(TheTitleText, TheTitleFont).Height;
}
// Calculating the starting x coordinate that the printing process will start from
float CurrentX = (float)LeftMargin;
if (IsCenterOnPage)
CurrentX += (((float)PageWidth - (float)RightMargin - (float)LeftMargin) - mColumnPointsWidth[mColumnPoint]) / 2.0F;
// Setting the HeaderFore style
Color HeaderForeColor = TheDataGridView.ColumnHeadersDefaultCellStyle.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.ColumnHeadersDefaultCellStyle.BackColor;
// If there is no special HeaderBack style, then use the default DataGridView style
if (HeaderBackColor.IsEmpty)
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.ColumnHeadersDefaultCellStyle.Font;
//if (HeaderFont == null) // If there is no special HeaderFont style, then use the default DataGridView font style
// HeaderFont = TheDataGridView.DefaultCellStyle.Font;
Font HeaderFont = null;
if (TheDataGridView.ColumnHeadersDefaultCellStyle.Font != null)
...{
HeaderFont = new Font(TheDataGridView.ColumnHeadersDefaultCellStyle.Font.FontFamily,
TheDataGridView.ColumnHeadersDefaultCellStyle.Font.Size * mRatio);
}
if (HeaderFont == null)
...{
HeaderFont = new Font(TheDataGridView.DefaultCellStyle.Font.FontFamily,
TheDataGridView.DefaultCellStyle.Font.Size * mRatio);
}
// Calculating and drawing the HeaderBounds
RectangleF HeaderBounds = new RectangleF(CurrentX, CurrentY, mColumnPointsWidth[mColumnPoint], RowHeaderHeight);
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;
float ColumnWidth;
for (int i = (int)mColumnPoints[mColumnPoint].GetValue(0); i < (int)mColumnPoints[mColumnPoint].GetValue(1); i++)
...{
if (!TheDataGridView.Columns[i].Visible) continue; // If the column is not visible then ignore this iteration
ColumnWidth = ColumnsWidth[i];
// Check the CurrentCell alignment and apply it to the CellFormat
if (TheDataGridView.ColumnHeadersDefaultCellStyle.Alignment.ToString().Contains("Right"))
CellFormat.Alignment = StringAlignment.Far;
else if (TheDataGridView.ColumnHeadersDefaultCellStyle.Alignment.ToString().Contains("Center"))
CellFormat.Alignment = StringAlignment.Center;
else
CellFormat.Alignment = StringAlignment.Near;
CellBounds = new RectangleF(CurrentX, CurrentY, ColumnWidth, RowHeaderHeight);
// 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, CurrentX, CurrentY, ColumnWidth, RowHeaderHeight);
CurrentX += ColumnWidth;
}
CurrentY += RowHeaderHeight;
}
/**//// <summary>
/// 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
/// </summary>
/// <param name="g"></param>
/// <returns>bool</returns>
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 = null;
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;
float CurrentX;
float ColumnWidth;
while (CurrentRow < TheDataGridView.Rows.Count)
...{
// Print the cells of the CurrentRow only if that row is visible
if (TheDataGridView.Rows[CurrentRow].Visible)
...{
// Setting the row font style
//RowFont = TheDataGridView.Rows[CurrentRow].DefaultCellStyle.Font;
if (TheDataGridView.Rows[CurrentRow].DefaultCellStyle.Font != null)
...{
RowFont = new Font(TheDataGridView.Rows[CurrentRow].DefaultCellStyle.Font.FontFamily,
TheDataGridView.Rows[CurrentRow].DefaultCellStyle.Font.Size * mRatio);
}
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;
RowFont = new Font(TheDataGridView.DefaultCellStyle.Font.FontFamily,
TheDataGridView.DefaultCellStyle.Font.Size * mRatio);
// 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 the there is no special RowBack style of the CurrentRow
* then use the default one associated with the DataGridView control
*/
if (RowBackColor.IsEmpty)
...{
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 = (float)LeftMargin;
if (IsCenterOnPage)
CurrentX += (((float)PageWidth - (float)RightMargin - (float)LeftMargin) - mColumnPointsWidth[mColumnPoint]) / 2.0F;
// Calculating the entire CurrentRow bounds
RowBounds = new RectangleF(CurrentX, CurrentY, mColumnPointsWidth[mColumnPoint], RowsHeight[CurrentRow]);
// 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 = (int)mColumnPoints[mColumnPoint].GetValue(0); CurrentCell < (int)mColumnPoints[mColumnPoint].GetValue(1); CurrentCell++)
...{
if (!TheDataGridView.Columns[CurrentCell].Visible) continue; // If the cell is belong to invisible column, then ignore this iteration
// Check the CurrentCell alignment and apply it to the CellFormat
if (TheDataGridView.Columns[CurrentCell].DefaultCellStyle.Alignment.ToString().Contains("Right"))
CellFormat.Alignment = StringAlignment.Far;
else if (TheDataGridView.Columns[CurrentCell].DefaultCellStyle.Alignment.ToString().Contains("Center"))
CellFormat.Alignment = StringAlignment.Center;
else
CellFormat.Alignment = StringAlignment.Near;
ColumnWidth = ColumnsWidth[CurrentCell];
RectangleF CellBounds = new RectangleF(CurrentX, CurrentY, ColumnWidth, RowsHeight[CurrentRow]);
// Printing the cell text
g.DrawString(TheDataGridView.Rows[CurrentRow].Cells[CurrentCell].EditedFormattedValue.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, CurrentX, CurrentY, ColumnWidth, RowsHeight[CurrentRow]);
CurrentX += ColumnWidth;
}
CurrentY += RowsHeight[CurrentRow];
/**//* 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 ((int)CurrentY > (PageHeight - TopMargin - BottomMargin))
...{
CurrentRow++;
return true;
}
}
CurrentRow++;
}
CurrentRow = 0;
// Continue to print the next group of columns
mColumnPoint++;
// Which means all columns are printed
if (mColumnPoint == mColumnPoints.Count)
...{
mColumnPoint = 0;
return false;
}
else
return true;
}
/**//// <summary>
/// The method that calls all other functions
/// </summary>
/// <param name="g"></param>
/// <returns>bool</returns>
public bool DrawDataGridView(Graphics g)
...{
try
...{
Calculate(g);
DrawHeader(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;
}
}
}