|
That was a wonderful job . You made my printing so easy. Now i dont need to border myselp about some report applications.. Thanks a bunch..
A Software developer from Nigeria.
Owoeye Ayobami
|
|
|
|
|
Thanx, this code is great!
how can i print the total pages number near the "Page n" string?
|
|
|
|
|
This is very good tool!. I'm want use it in my project. Please, answer what license terms You use.
|
|
|
|
|
Well this code is very useful, many thanks, I used the "title" to add more data taken from my form (nothing fancy only using String.Concat and chr(13),chr(10), to append a new line displaying certain textboxes' text), but I'm now trying to add an image before the title, which has proven more troublesome. I'm Working with VB.net 2008, does anyone knows how I can achieve it?
|
|
|
|
|
I found the way, it wasn't very hard I just approached it the wrong way. Just add something like this code on the "Private Sub DrawHeader" -> "If IsWithTitle Then":
Dim imageFile As Image = Image.FromFile(Application.StartupPath & "image.jpg")
g.DrawImage(imageFile, New PointF(CSng(LeftMargin), CurrentY))
Then using "CurrentY" you move the text down, so you can add more lines of text, draw shapes or whatever.
Well sorry for not tryin' harder before asking, hope this serves someone.
|
|
|
|
|
Hello Daniel01983
How do you center your image to the print page?
|
|
|
|
|
Not sure if anyone will see this, but in C# I did my logo like this:
if (IsWithTitle)
{
RectangleF LogoRectangle;
Image companyLogoImage = Image.FromFile(TheLogoPath);
if (companyLogoImage.Height > 500 || companyLogoImage.Width > 500)
{
LogoRectangle = new RectangleF((float)PageWidth - (float)(PageWidth / 2) - (float)((companyLogoImage.Width * .1) / 2), CurrentY, (float)(companyLogoImage.Width * .1), (float)(companyLogoImage.Height * .1));
}
else
{
LogoRectangle = new RectangleF((float)PageWidth - (float)(PageWidth / 2) - (float)((companyLogoImage.Width) / 2), CurrentY, (float)(companyLogoImage.Width), (float)(companyLogoImage.Height));
}
g.DrawImage(companyLogoImage, LogoRectangle);
CurrentY += LogoRectangle.Height;
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;
}
|
|
|
|
|
I have been using this class for awhile on an application where I work. It's a wonderful piece of code. Recently I used it to build another application for a hospital, and it proved to be difficult to use this class to make a report fit to a very specific page width. However, slightly modified, I was able to implement my own word wrapping and make it fit on a legal sheet of paper, in landscape mode.
Thank you for this code!
|
|
|
|
|
I try the code, the chinese characters can't be printed in the row cell, though the chinese characters can be printed in the head's cell. I check the size of the row cell, it is enough for the chinese character.I try like this:
>//g.DrawString(TheDataGridView.Rows[CurrentRow].Cells[CurrentCell].EditedFormattedValue.ToString(), RowFont, RowForeBrush, CellBounds, CellFormat);
g.DrawString("张", RowFont, RowForeBrush, CellBounds, CellFormat);
I change the first line of code with the second line of code.The result is:
the header is right, but the row cell is null. I donn't know the reason.
|
|
|
|
|
Thanks man,
works as a machine gun.I thought that it's some kind of a custom datagridview or some other custom control and it would be much harder for me to actually integrate that stuff in my app.Great article.Very useful stuff.
Regards
|
|
|
|
|
Does anyone have the class for VB.NET 2008? I've tried creating the classes already posted but I get a lot of errors because of the difference in VB versions.
|
|
|
|
|
For somereason i cannot get this to display my datagridview that i have displayed on a windows form. Print preview and print only display blank page. I pointed the print class to my datagrid but no luck. using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Printing;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Printing;
namespace File_Generation_System
{
public partial class exceptionFrm : Form
{
public DataSet ds;
public BindingSource mybind;
public bool errorflag;
PrintDocument MyPrintDocument = new PrintDocument();
DataGridViewPrinter MyDataGridViewPrinter;
public exceptionFrm()
{
InitializeComponent();
}
private void exceptionFrm_Load(object sender, EventArgs e)
{
comboBox1.SelectedIndex = 0;
try
{
mybind = new BindingSource();
configure.read_xml_files();
ds = new DataSet();
ds.ReadXml(configure.vrdb);
mybind.DataSource = ds;
mybind.DataMember = "inquiry_data";
SetupColumns(ds);
dataGridView1.DataSource = ds;
dataGridView1.AutoGenerateColumns = false;
dataGridView1.DataSource = mybind;
if (ds.Tables.Count == 0)
throw new Exception();
}
catch (ArgumentException ex)
{
errorflag = true;
listBox1.Visible = true;
listBox1.Items.Add("There are no records in the database");
}
}
private void SetupColumns(DataSet ds)
{
DataGridViewTextBoxColumn roName = new DataGridViewTextBoxColumn();
roName.DataPropertyName = "ro_name";
roName.HeaderText = "Registered Owner Name";
roName.ValueType = typeof(string);
dataGridView1.Columns.Add(roName);
DataGridViewTextBoxColumn roNameOrAddress = new DataGridViewTextBoxColumn();
roNameOrAddress.DataPropertyName = "ro_name_or_address";
roNameOrAddress.HeaderText = "Registered Owner Name/or Address";
roNameOrAddress.ValueType = typeof(string);
dataGridView1.Columns.Add(roNameOrAddress);
DataGridViewTextBoxColumn licenseNumber = new DataGridViewTextBoxColumn();
licenseNumber.DataPropertyName = "license_number";
licenseNumber.HeaderText = "License Number";
licenseNumber.ValueType = typeof(string);
dataGridView1.Columns.Add(licenseNumber);
DataGridViewTextBoxColumn regExpireDate = new DataGridViewTextBoxColumn();
regExpireDate.DataPropertyName = "reg_expire_date";
regExpireDate.HeaderText = "Registration Expiration Date";
regExpireDate.ValueType = typeof(string);
dataGridView1.Columns.Add(regExpireDate);
DataGridViewTextBoxColumn make = new DataGridViewTextBoxColumn();
make.DataPropertyName = "make";
make.HeaderText = "Make of Car";
make.ValueType = typeof(string);
dataGridView1.Columns.Add(make);
DataGridViewTextBoxColumn vin = new DataGridViewTextBoxColumn();
vin.DataPropertyName = "vin";
vin.HeaderText = "VIN";
vin.ValueType = typeof(string);
dataGridView1.Columns.Add(vin);
DataGridViewTextBoxColumn roCity = new DataGridViewTextBoxColumn();
roCity.DataPropertyName = "ro_city";
roCity.HeaderText = "City";
roCity.ValueType = typeof(string);
dataGridView1.Columns.Add(roCity);
DataGridViewTextBoxColumn roZip = new DataGridViewTextBoxColumn();
roZip.DataPropertyName = "ro_zip";
roZip.HeaderText = "ZIP";
roZip.ValueType = typeof(string);
dataGridView1.Columns.Add(roZip);
DataGridViewTextBoxColumn roCountyCode = new DataGridViewTextBoxColumn();
roCountyCode.DataPropertyName = "ro_county_code";
roCountyCode.HeaderText = "County Code";
roCountyCode.ValueType = typeof(string);
dataGridView1.Columns.Add(roCountyCode);
DataGridViewTextBoxColumn asOfDate = new DataGridViewTextBoxColumn();
asOfDate.DataPropertyName = "as_of_date";
asOfDate.HeaderText = "As of Date";
asOfDate.ValueType = typeof(string);
dataGridView1.Columns.Add(asOfDate);
DataGridViewTextBoxColumn fileCode = new DataGridViewTextBoxColumn();
fileCode.DataPropertyName = "file_code";
fileCode.HeaderText = "File Code";
fileCode.ValueType = typeof(string);
dataGridView1.Columns.Add(fileCode);
DataGridViewTextBoxColumn yearModel = new DataGridViewTextBoxColumn();
yearModel.DataPropertyName = "year_model";
yearModel.HeaderText = "Model Year";
yearModel.ValueType = typeof(string);
dataGridView1.Columns.Add(yearModel);
DataGridViewTextBoxColumn citeNumber = new DataGridViewTextBoxColumn();
citeNumber.DataPropertyName = "user_information";
citeNumber.HeaderText = "Citation Number";
citeNumber.ValueType = typeof(string);
dataGridView1.Columns.Add(citeNumber);
DataGridViewTextBoxColumn paperIssueDate = new DataGridViewTextBoxColumn();
paperIssueDate.DataPropertyName = "paper_issue_date";
paperIssueDate.HeaderText = "Date last document was issued";
paperIssueDate.ValueType = typeof(string);
dataGridView1.Columns.Add(paperIssueDate);
DataGridViewTextBoxColumn recordConditionCode = new DataGridViewTextBoxColumn();
recordConditionCode.DataPropertyName = "record_condition_code";
recordConditionCode.HeaderText = "Record Condtion code";
recordConditionCode.ValueType = typeof(string);
dataGridView1.Columns.Add(recordConditionCode);
DataGridViewTextBoxColumn recordCondtionCodeDate = new DataGridViewTextBoxColumn();
recordCondtionCodeDate.DataPropertyName = "record_condition_code_date";
recordCondtionCodeDate.HeaderText = "Date Record Condition Code was Entered";
recordCondtionCodeDate.ValueType = typeof(string);
dataGridView1.Columns.Add(recordCondtionCodeDate);
DataGridViewTextBoxColumn recordRemarks = new DataGridViewTextBoxColumn();
recordRemarks.DataPropertyName = "record_remarks";
recordRemarks.HeaderText = "Record Remarks";
recordRemarks.ValueType = typeof(string);
dataGridView1.Columns.Add(recordRemarks);
DataGridViewTextBoxColumn errorCode = new DataGridViewTextBoxColumn();
errorCode.DataPropertyName = "error_code";
errorCode.HeaderText = "Error Code";
errorCode.ValueType = typeof(string);
dataGridView1.Columns.Add(errorCode);
DataGridViewTextBoxColumn errorMessage = new DataGridViewTextBoxColumn();
errorMessage.DataPropertyName = "error_message";
errorMessage.HeaderText = "Error Message";
errorMessage.ValueType = typeof(string);
dataGridView1.Columns.Add(errorMessage);
DataGridViewTextBoxColumn errorDate = new DataGridViewTextBoxColumn();
errorDate.DataPropertyName = "error_date";
errorDate.HeaderText = "Error Date";
errorDate.ValueType = typeof(string);
dataGridView1.Columns.Add(errorDate);
DataGridViewTextBoxColumn datePaid = new DataGridViewTextBoxColumn();
datePaid.DataPropertyName = "date_paid";
datePaid.HeaderText = "Date Paid";
datePaid.ValueType = typeof(string);
dataGridView1.Columns.Add(datePaid);
DataGridViewTextBoxColumn removalCode = new DataGridViewTextBoxColumn();
removalCode.DataPropertyName = "removal_code";
removalCode.HeaderText = "DMV Removal Code";
removalCode.ValueType = typeof(string);
dataGridView1.Columns.Add(removalCode);
DataGridViewTextBoxColumn removalDate = new DataGridViewTextBoxColumn();
removalDate.DataPropertyName = "removed_date";
removalDate.HeaderText = "Date DMV removed hold";
removalDate.ValueType = typeof(string);
dataGridView1.Columns.Add(removalDate);
DataGridViewTextBoxColumn removalMessage = new DataGridViewTextBoxColumn();
removalMessage.DataPropertyName = "removal_message";
removalMessage.HeaderText = "Removal Message";
removalMessage.ValueType = typeof(string);
dataGridView1.Columns.Add(removalMessage);
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
}
private bool SetupThePrinting()
{
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)
return false;
MyPrintDocument.DocumentName = "Customers Report";
MyPrintDocument.PrinterSettings =
MyPrintDialog.PrinterSettings;
MyPrintDocument.DefaultPageSettings =
MyPrintDialog.PrinterSettings.DefaultPageSettings;
MyPrintDocument.DefaultPageSettings.Margins =
new Margins(40, 40, 40, 40);
if (MessageBox.Show("Do you want the report to be centered on the page",
"InvoiceManager - Center on Page", MessageBoxButtons.YesNo,
MessageBoxIcon.Question) == DialogResult.Yes)
MyDataGridViewPrinter = new DataGridViewPrinter(dataGridView1,
MyPrintDocument, true, true, "Customers", new Font("Tahoma", 18,
FontStyle.Bold, GraphicsUnit.Point), Color.Black, true);
else
MyDataGridViewPrinter = new DataGridViewPrinter(dataGridView1,
MyPrintDocument, false, true, "Customers", new Font("Tahoma", 18,
FontStyle.Bold, GraphicsUnit.Point), Color.Black, true);
return true;
}
private void exitFilterViewToolStripMenuItem_Click(object sender, EventArgs e)
{
this.Close();
}
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
}
private void searchBtn_Click(object sender, EventArgs e)
{
if (textBox1.Text.Trim() == "")
{
listBox1.Visible = true;
listBox1.Items.Add("Seach criteria empty");
}
if (textBox1.Text.Trim().Length > 0)
{
listBox1.Items.Clear();
listBox1.Visible = false;
if (comboBox1.Text.Substring(0, 1) == "0") mybind.Filter = "";
if (comboBox1.Text.Substring(0, 1) == "C") mybind.Filter = "rejection_code = 'C'";
if (comboBox1.Text.Substring(0, 1) == "R") mybind.Filter = "record_condition_code > '0'";
if (comboBox1.Text.Substring(0, 1) == "V") mybind.Filter = "vin like '%" +
textBox1.Text.Trim() + "%'";
if (comboBox1.Text.Substring(0, 1) == "L") mybind.Filter = "license_number like '%" +
textBox1.Text + "%'";
if (comboBox1.Text.Substring(0, 1) == "M") mybind.Filter = "make like '%" +
textBox1.Text + "%'";
if (comboBox1.Text.Substring(0, 1) == "E") mybind.Filter = "error_code > '0'";
if (comboBox1.Text.Substring(0, 1) == "P") mybind.Filter = "user_information like '%" +
textBox1.Text + "%'";
if (comboBox1.Text.Substring(0, 1) == "S") mybind.Filter = "removal_code > '0'";
}
}
private void printBtn_Click(object sender, EventArgs e)
{
if (SetupThePrinting())
MyPrintDocument.Print();
}
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
bool more = MyDataGridViewPrinter.DrawDataGridView(e.Graphics);
if (more == true)
e.HasMorePages = true;
}
private void btnPrintPreview_Click(object sender, EventArgs e)
{
if (SetupThePrinting())
{
PrintPreviewDialog MyPrintPreviewDialog = new PrintPreviewDialog();
MyPrintPreviewDialog.Document = MyPrintDocument;
MyPrintPreviewDialog.ShowDialog();
}
}
}
}
|
|
|
|
|
Hi,
I have the same problem
snky
|
|
|
|
|
Hi,
I had similar problem, finally I solved it. You may have the same issue. What I did is
to the .Designer.cs part of my project I added necessary lines for PrintDocument object.
1-this.MyPrintDocument = new System.Drawing.Printing.PrintDocument();
2- // MyPrintDocument
//
this.MyPrintDocument.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(this.MyPrintDocument_PrintPage);
3-private System.Drawing.Printing.PrintDocument MyPrintDocument;
I hope it helps you.
snky
|
|
|
|
|
Where exactly did you put this code?
|
|
|
|
|
Thanks, it works!!
For others: u have to put the code under InitializeComponent() in the Designer.cs where some of this....-elements are standing.
this.xyz = new xyz.....
this.xyz = new xyz.....
this.xyz = new xyz.....
this.xyz = new xyz.....
...
this.MyPrintDocument = new System.Drawing.Printing.PrintDocument();
this.MyPrintDocument.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(this.MyPrintDocument_PrintPage);
...
this.SuspendLayout();
-------------------------
That's what I do! Work's fine!
|
|
|
|
|
You have to add Event Handler.
private void printDocument1_PrintPage(object sender, PrintPageEventArgs e)
{
DataGridViewPrinter printer = new DataGridViewPrinter(this.dataGridView1, this.printDocument1, true, false, "", new Font("Arial", 10), Color.Red, false);
Graphics g = e.Graphics;
printer.DrawDataGridView(g);
}
Also, you have to add print action.
private void printToolStripMenuItem_Click(object sender, EventArgs e)
{
this.printDocument1.Print();
}
|
|
|
|
|
Hello I'm new to this forum. And a little new to c#. I'm trying this method but it keeps giving me blank pages. What am I missing? Maybe I should add a printToolStripMenu? Is that req. for this programm to run?
|
|
|
|
|
Hi ,
I have browsed over the messages and got idea from Stephen long , by calculating the width of the columns , and then have to calculate the height of each row , then have to assign the width and height in the Calucate function in DataGridViewPrinter.Cs file.
Then able to wrap the text in the datagridview.
Thanks for the wonderfull article , it's nice to know such wonderfull ideas.
Thanks,
N.S.Ponraja.
modified on Thursday, August 20, 2009 1:47 AM
|
|
|
|
|
sir ur code is very use ful to me. But iwant to use it in vb.net so how can i use it there.
|
|
|
|
|
Attached a modified VB code with some new features:
- Optional displaying of total page number
- Easier call to print or preview:
Initial call to print:
Dim prt As New DataGridPrinter(Me.DataGridView1)
With prt
.TitleForeColor = Color.Red
.TitleFont = New Font("Arial", 16, FontStyle.Bold, GraphicsUnit.Point)
.SetPageSettings() 'optional to show dialog, otherweise remove line
.Title = "Test pages ..."
.Print(PrintAction.PrintToPreview)
End With
------------------------------------------------------
'Modified class
Imports System
Imports System.Text
Imports System.Collections
Imports System.Collections.Generic
Imports System.Drawing
Imports System.Drawing.Printing
Imports System.Data
Imports System.Windows.Forms
Public Class DataGridPrinter
Private mPrt As DataGridViewPrinter
Private WithEvents mDoc As PrintDocument
Private mDgr As DataGridView
Private mPageSet As PageSettings
Private mDlgPre As PrintPreviewDialog
Private mDlgPrt As PrintDialog
#Region " Properties "
Private mTitle As String = "Title"
''' <summary>
''' Page title
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Property Title() As String
Get
Return mTitle
End Get
Set(ByVal value As String)
mTitle = value
End Set
End Property
Private mTitleFont As Font
''' <summary>
''' Font of title
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Property TitleFont() As Font
Get
Return mTitleFont
End Get
Set(ByVal value As Font)
mTitleFont = value
End Set
End Property
Private mColor As Color = Color.Black
''' <summary>
''' Title forecolor
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Property TitleForeColor() As Color
Get
Return mColor
End Get
Set(ByVal value As Color)
mColor = value
End Set
End Property
Private mShowTitle As Boolean = True
''' <summary>
''' Will title be shown?
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Property ShowTitle() As Boolean
Get
Return mShowTitle
End Get
Set(ByVal value As Boolean)
mShowTitle = value
End Set
End Property
Private mCenter As Boolean = False
''' <summary>
''' Content centered on page
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Property CenterOnPage() As Boolean
Get
Return mCenter
End Get
Set(ByVal value As Boolean)
mCenter = value
End Set
End Property
Private mPageNumber As Boolean = True
''' <summary>
''' Show page numbers
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Property ShowPageNumbers() As Boolean
Get
Return mPageNumber
End Get
Set(ByVal value As Boolean)
mPageNumber = value
End Set
End Property
Private mShowTotalNumber As Boolean = True
''' <summary>
''' Show total page numbers
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Property ShowTotalNumber() As Boolean
Get
Return mShowTotalNumber
End Get
Set(ByVal value As Boolean)
mShowTotalNumber = value
End Set
End Property
Private mPageNumberText As String = "Page"
''' <summary>
''' Displayed text: 'PAGE ...'
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Property PageNumberText() As String
Get
Return mPageNumberText
End Get
Set(ByVal value As String)
mPageNumberText = value
End Set
End Property
#End Region
Private Sub mDoc_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles mDoc.PrintPage
e.HasMorePages = mPrt.DrawDataGridView(e.Graphics)
End Sub
Public Sub New(ByVal dgr As DataGridView)
mDgr = dgr
mTitleFont = dgr.Font
End Sub
''' <summary>
''' Main sub to start printing
''' </summary>
''' <param name="Action"></param>
''' <remarks></remarks>
Public Sub Print(Optional ByVal Action As PrintAction = PrintAction.PrintToPreview)
mDoc = New PrintDocument
If Not IsNothing(mPageSet) Then
mDoc.PrinterSettings = mPageSet.PrinterSettings
mDoc.DefaultPageSettings = mPageSet.PrinterSettings.DefaultPageSettings
mDoc.DefaultPageSettings.Margins = mPageSet.Margins
End If
Select Case Action
Case PrintAction.PrintToPreview
mDlgPre = New PrintPreviewDialog
With mDlgPre
.Document = mDoc
mPrt = New DataGridPrinter.DataGridViewPrinter(mDgr, _
mDoc, CenterOnPage, ShowTitle, Title, _
TitleFont, TitleForeColor, ShowPageNumbers, _
ShowTotalNumber, PageNumberText)
If IsNothing(mPageSet) Then
mDoc.DefaultPageSettings.Margins = New Margins(40, 40, 40, 40)
End If
If Not .ShowDialog = DialogResult.OK Then
Exit Sub
End If
End With
mDlgPre = Nothing
Case PrintAction.PrintToPrinter
mDlgPrt = New PrintDialog
With mDlgPrt
.PrintToFile = False
.AllowPrintToFile = False
If Not .ShowDialog = DialogResult.OK Then Exit Sub
If IsNothing(mPageSet) Then
mDoc.PrinterSettings = .PrinterSettings
mDoc.DefaultPageSettings = .PrinterSettings.DefaultPageSettings
Else
mDoc.DefaultPageSettings.Margins = New Margins(40, 40, 40, 40)
End If
mPrt = New DataGridPrinter.DataGridViewPrinter(mDgr, _
mDoc, CenterOnPage, ShowTitle, Title, _
TitleFont, TitleForeColor, ShowPageNumbers, _
ShowTotalNumber, PageNumberText)
mDoc.Print()
End With
mDlgPrt = Nothing
Case Else
mDlgPrt = New PrintDialog
With mDlgPrt
.PrintToFile = True
.AllowPrintToFile = True
If IsNothing(mPageSet) Then
mDoc.PrinterSettings = .PrinterSettings
mDoc.DefaultPageSettings = .PrinterSettings.DefaultPageSettings
Else
mDoc.DefaultPageSettings.Margins = New Margins(40, 40, 40, 40)
End If
If Not .ShowDialog = DialogResult.OK Then Exit Sub
mPrt = New DataGridPrinter.DataGridViewPrinter(mDgr, _
mDoc, CenterOnPage, ShowTitle, Title, _
TitleFont, TitleForeColor, ShowPageNumbers, _
ShowTotalNumber, PageNumberText)
mDoc.Print()
End With
mDlgPrt = Nothing
End Select
mDoc = Nothing
mPrt = Nothing
End Sub
Public Sub SetPageSettings()
Dim dlg As New PageSetupDialog
mDoc = New PrintDocument
With dlg
.Document = mDoc
If .ShowDialog = DialogResult.OK Then
ApplyPageSettings(dlg.PageSettings)
End If
End With
End Sub
Public Sub ApplyPageSettings(ByVal Settings As PageSettings)
mPageSet = Settings
End Sub
Public Class DataGridViewPrinter
Private TheDataGridView As DataGridView
' The DataGridView Control which will be printed
Private ThePrintDocument As PrintDocument
' The PrintDocument to be used for printing
Private IsCenterOnPage As Boolean
' Determine if the report will be printed in the Top-Center of the page
Private IsWithTitle As Boolean
' Determine if the page contain title text
Private TheTitleText As String
' The title text to be printed in each page (if IsWithTitle is set to true)
Private TheTitleFont As Font
' The font to be used with the title text (if IsWithTitle is set to true)
Private TheTitleColor As Color
' The color to be used with the title text (if IsWithTitle is set to true)
Private IsWithPaging As Boolean
' Determine if paging is used
Shared CurrentRow As Integer
' A static parameter that keep track on which Row (in the DataGridView control) that should be printed
Shared PageNumber As Integer
' Temp pagenumbers for total
'Private mPages As Integer
' Total page number
Private Pages As Integer = 0
Private PageWidth As Integer
Private PageHeight As Integer
Private LeftMargin As Integer
Private TopMargin As Integer
Private RightMargin As Integer
Private BottomMargin As Integer
Private OnlyCount As Boolean
Private CurrentY As Single
' 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
Private RowHeaderHeight As Single
Private RowsHeight As List(Of Single)
Private ColumnsWidth As List(Of Single)
Private TheDataGridViewWidth As Single
' 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
Private mColumnPoints As List(Of Integer())
Private mColumnPointsWidth As List(Of Single)
Private mColumnPoint As Integer
' Indicator if printing starts
Private mStart As Boolean
' Show total page numbers?
Private mTotalNumber As Boolean
Private mPageNumberText As String
'Used to call printing and to calculate total number
Private Sub CalcPages()
If Not mTotalNumber Then Exit Sub
mStart = True
Pages = 0
Dim c As New Control
Dim e As Graphics = c.CreateGraphics
Do Until Not DrawDataGridView(e)
Loop
c.Dispose()
c = Nothing
CurrentRow = 0
mStart = False
End Sub
' The class constructor
Public Sub New(ByVal aDataGridView As DataGridView, _
ByVal aPrintDocument As PrintDocument, _
ByVal CenterOnPage As Boolean, _
ByVal WithTitle As Boolean, _
ByVal aTitleText As String, _
ByVal aTitleFont As Font, _
ByVal aTitleColor As Color, _
ByVal WithPaging As Boolean, _
ByVal ShowTotalNumber As Boolean, _
Optional ByVal PageNumberText As String = "Page")
TheDataGridView = aDataGridView
ThePrintDocument = aPrintDocument
IsCenterOnPage = CenterOnPage
IsWithTitle = WithTitle
TheTitleText = aTitleText
TheTitleFont = aTitleFont
TheTitleColor = aTitleColor
IsWithPaging = WithPaging
mTotalNumber = ShowTotalNumber
mPageNumberText = PageNumberText
PageNumber = 0
mStart = True
RowsHeight = New List(Of Single)()
ColumnsWidth = New List(Of Single)()
mColumnPoints = New List(Of Integer())()
mColumnPointsWidth = New List(Of Single)()
' Claculating the PageWidth and the PageHeight
If Not ThePrintDocument.DefaultPageSettings.Landscape Then
PageWidth = ThePrintDocument.DefaultPageSettings.PaperSize.Width
PageHeight = ThePrintDocument.DefaultPageSettings.PaperSize.Height
Else
PageHeight = ThePrintDocument.DefaultPageSettings.PaperSize.Width
PageWidth = ThePrintDocument.DefaultPageSettings.PaperSize.Height
End If
' Claculating the page margins
LeftMargin = ThePrintDocument.DefaultPageSettings.Margins.Left - ThePrintDocument.DefaultPageSettings.HardMarginX
TopMargin = ThePrintDocument.DefaultPageSettings.Margins.Top - ThePrintDocument.DefaultPageSettings.HardMarginY
RightMargin = ThePrintDocument.DefaultPageSettings.Margins.Right + ThePrintDocument.DefaultPageSettings.HardMarginX
BottomMargin = ThePrintDocument.DefaultPageSettings.Margins.Bottom + ThePrintDocument.DefaultPageSettings.HardMarginY
' First, the current row to be printed is the first row in the DataGridView control
CurrentRow = 0
CalcPages()
End Sub
' 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
Private Sub Calculate(ByVal g As Graphics)
If mStart Then
' Just calculate once
Dim tmpSize As New SizeF()
Dim tmpFont As Font
Dim tmpWidth As Single
TheDataGridViewWidth = 0
For i As Integer = 0 To TheDataGridView.Columns.Count - 1
tmpFont = TheDataGridView.ColumnHeadersDefaultCellStyle.Font
If tmpFont Is Nothing Then
' If there is no special HeaderFont style, then use the default DataGridView font style
tmpFont = TheDataGridView.DefaultCellStyle.Font
End If
tmpSize = g.MeasureString(TheDataGridView.Columns(i).HeaderText, tmpFont)
tmpWidth = tmpSize.Width
RowHeaderHeight = tmpSize.Height
For j As Integer = 0 To TheDataGridView.Rows.Count - 1
tmpFont = TheDataGridView.Rows(j).DefaultCellStyle.Font
If tmpFont Is Nothing Then
' If the there is no special font style of the CurrentRow, then use the default one associated with the DataGridView control
tmpFont = TheDataGridView.DefaultCellStyle.Font
End If
tmpSize = g.MeasureString("Anything", tmpFont)
RowsHeight.Add(tmpSize.Height)
tmpSize = g.MeasureString(TheDataGridView.Rows(j).Cells(i).EditedFormattedValue.ToString(), tmpFont)
If tmpSize.Width > tmpWidth Then
tmpWidth = tmpSize.Width
End If
Next
If TheDataGridView.Columns(i).Visible Then
TheDataGridViewWidth += tmpWidth
End If
ColumnsWidth.Add(tmpWidth)
Next
' 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
Dim k As Integer
Dim mStartPoint As Integer = 0
For k = 0 To TheDataGridView.Columns.Count - 1
If TheDataGridView.Columns(k).Visible Then
mStartPoint = k
Exit For
End If
Next
Dim mEndPoint As Integer = TheDataGridView.Columns.Count
For k = TheDataGridView.Columns.Count - 1 To 0 Step -1
If TheDataGridView.Columns(k).Visible Then
mEndPoint = k + 1
Exit For
End If
Next
Dim mTempWidth As Single = TheDataGridViewWidth
Dim mTempPrintArea As Single = CSng(PageWidth) - CSng(LeftMargin) - CSng(RightMargin)
' We only care about handling where the total datagridview width is bigger then the print area
If TheDataGridViewWidth > mTempPrintArea Then
mTempWidth = 0.0F
For k = 0 To TheDataGridView.Columns.Count - 1
If TheDataGridView.Columns(k).Visible Then
mTempWidth += ColumnsWidth(k)
' If the width is bigger than the page area, then define a new column print range
If mTempWidth > mTempPrintArea Then
mTempWidth -= ColumnsWidth(k)
mColumnPoints.Add(New Integer() {mStartPoint, mEndPoint})
mColumnPointsWidth.Add(mTempWidth)
mStartPoint = k
mTempWidth = ColumnsWidth(k)
End If
End If
' Our end point is actually one index above the current index
mEndPoint = k + 1
Next
End If
' Add the last set of columns
mColumnPoints.Add(New Integer() {mStartPoint, mEndPoint})
mColumnPointsWidth.Add(mTempWidth)
mColumnPoint = 0
mStart = False
End If
End Sub
' The funtion that print the title, page number, and the header row
Private Sub DrawHeader(ByVal g As Graphics)
CurrentY = CSng(TopMargin)
PageNumber += 1
' Printing the page number (if isWithPaging is set to true)
If IsWithPaging Then
Dim PageString As String = mPageNumberText & " " & PageNumber.ToString() & IIf(mTotalNumber, "/" & Pages, "")
Dim PageStringFormat As New StringFormat()
PageStringFormat.Trimming = StringTrimming.Word
PageStringFormat.FormatFlags = StringFormatFlags.NoWrap Or StringFormatFlags.LineLimit Or StringFormatFlags.NoClip
PageStringFormat.Alignment = StringAlignment.Far
Dim PageStringFont As New Font("Tahoma", 8, FontStyle.Regular, GraphicsUnit.Point)
Dim PageStringRectangle As New RectangleF(CSng(LeftMargin), CurrentY, CSng(PageWidth) - CSng(RightMargin) - CSng(LeftMargin), g.MeasureString(PageString, PageStringFont).Height)
g.DrawString(PageString, PageStringFont, New SolidBrush(Color.Black), PageStringRectangle, PageStringFormat)
CurrentY += g.MeasureString(PageString, PageStringFont).Height
End If
' Printing the title (if IsWithTitle is set to true)
If IsWithTitle Then
Dim TitleFormat As New StringFormat()
TitleFormat.Trimming = StringTrimming.Word
TitleFormat.FormatFlags = StringFormatFlags.NoWrap Or StringFormatFlags.LineLimit Or StringFormatFlags.NoClip
If IsCenterOnPage Then
TitleFormat.Alignment = StringAlignment.Center
Else
TitleFormat.Alignment = StringAlignment.Near
End If
Dim TitleRectangle As New RectangleF(CSng(LeftMargin), CurrentY, CSng(PageWidth) - CSng(RightMargin) - CSng(LeftMargin), g.MeasureString(TheTitleText, TheTitleFont).Height)
g.DrawString(TheTitleText, TheTitleFont, New SolidBrush(TheTitleColor), TitleRectangle, TitleFormat)
CurrentY += g.MeasureString(TheTitleText, TheTitleFont).Height
End If
' Calculating the starting x coordinate that the printing process will start from
Dim CurrentX As Single = CSng(LeftMargin)
If IsCenterOnPage Then
CurrentX += ((CSng(PageWidth) - CSng(RightMargin) - CSng(LeftMargin)) - mColumnPointsWidth(mColumnPoint)) / 2.0F
End If
' Setting the HeaderFore style
Dim HeaderForeColor As Color = TheDataGridView.ColumnHeadersDefaultCellStyle.ForeColor
If HeaderForeColor.IsEmpty Then
' If there is no special HeaderFore style, then use the default DataGridView style
HeaderForeColor = TheDataGridView.DefaultCellStyle.ForeColor
End If
Dim HeaderForeBrush As New SolidBrush(HeaderForeColor)
' Setting the HeaderBack style
Dim HeaderBackColor As Color = TheDataGridView.ColumnHeadersDefaultCellStyle.BackColor
If HeaderBackColor.IsEmpty Then
' If there is no special HeaderBack style, then use the default DataGridView style
HeaderBackColor = TheDataGridView.DefaultCellStyle.BackColor
End If
Dim HeaderBackBrush As New SolidBrush(HeaderBackColor)
' Setting the LinePen that will be used to draw lines and rectangles (derived from the GridColor property of the DataGridView control)
Dim TheLinePen As New Pen(TheDataGridView.GridColor, 1)
' Setting the HeaderFont style
Dim HeaderFont As Font = TheDataGridView.ColumnHeadersDefaultCellStyle.Font
If HeaderFont Is Nothing Then
' If there is no special HeaderFont style, then use the default DataGridView font style
HeaderFont = TheDataGridView.DefaultCellStyle.Font
End If
' Calculating and drawing the HeaderBounds
Dim HeaderBounds As 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
Dim CellFormat As New StringFormat()
CellFormat.Trimming = StringTrimming.Word
CellFormat.FormatFlags = StringFormatFlags.NoWrap Or StringFormatFlags.LineLimit Or StringFormatFlags.NoClip
' Printing each visible cell of the header row
Dim CellBounds As RectangleF
Dim ColumnWidth As Single
For i As Integer = CInt(mColumnPoints(mColumnPoint).GetValue(0)) To CInt(mColumnPoints(mColumnPoint).GetValue(1)) - 1
If Not TheDataGridView.Columns(i).Visible Then
Continue For
End If
' 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") Then
CellFormat.Alignment = StringAlignment.Far
ElseIf TheDataGridView.ColumnHeadersDefaultCellStyle.Alignment.ToString().Contains("Center") Then
CellFormat.Alignment = StringAlignment.Center
Else
CellFormat.Alignment = StringAlignment.Near
End If
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 Then
' Draw the cell border only if the HeaderBorderStyle is not None
g.DrawRectangle(TheLinePen, CurrentX, CurrentY, ColumnWidth, RowHeaderHeight)
End If
CurrentX += ColumnWidth
Next
CurrentY += RowHeaderHeight
End Sub
' 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 Function DrawRows(ByVal g As Graphics) As Boolean
' Setting the LinePen that will be used to draw lines and rectangles (derived from the GridColor property of the DataGridView control)
Dim TheLinePen As New Pen(TheDataGridView.GridColor, 1)
' The style paramters that will be used to print each cell
Dim RowFont As Font
Dim RowForeColor As Color
Dim RowBackColor As Color
Dim RowForeBrush As SolidBrush
Dim RowBackBrush As SolidBrush
Dim RowAlternatingBackBrush As SolidBrush
' Setting the format that will be used to print each cell
Dim CellFormat As New StringFormat()
CellFormat.Trimming = StringTrimming.Word
CellFormat.FormatFlags = StringFormatFlags.NoWrap Or StringFormatFlags.LineLimit
' Printing each visible cell
Dim RowBounds As RectangleF
Dim CurrentX As Single
Dim ColumnWidth As Single
While CurrentRow < TheDataGridView.Rows.Count
If TheDataGridView.Rows(CurrentRow).Visible Then
' 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 Is Nothing Then
' 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
End If
' Setting the RowFore style
RowForeColor = TheDataGridView.Rows(CurrentRow).DefaultCellStyle.ForeColor
If RowForeColor.IsEmpty Then
' 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
End If
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 Then
' 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)
End If
' Calculating the starting x coordinate that the printing process will start from
CurrentX = CSng(LeftMargin)
If IsCenterOnPage Then
CurrentX += ((CSng(PageWidth) - CSng(RightMargin) - CSng(LeftMargin)) - mColumnPointsWidth(mColumnPoint)) / 2.0F
End If
' Calculating the entire CurrentRow bounds
RowBounds = New RectangleF(CurrentX, CurrentY, mColumnPointsWidth(mColumnPoint), RowsHeight(CurrentRow))
' Filling the back of the CurrentRow
If CurrentRow Mod 2 = 0 Then
g.FillRectangle(RowBackBrush, RowBounds)
Else
g.FillRectangle(RowAlternatingBackBrush, RowBounds)
End If
' Printing each visible cell of the CurrentRow
For CurrentCell As Integer = CInt(mColumnPoints(mColumnPoint).GetValue(0)) To CInt(mColumnPoints(mColumnPoint).GetValue(1)) - 1
If Not TheDataGridView.Columns(CurrentCell).Visible Then
Continue For
End If
' 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") Then
CellFormat.Alignment = StringAlignment.Far
ElseIf TheDataGridView.Columns(CurrentCell).DefaultCellStyle.Alignment.ToString().Contains("Center") Then
CellFormat.Alignment = StringAlignment.Center
Else
CellFormat.Alignment = StringAlignment.Near
End If
ColumnWidth = ColumnsWidth(CurrentCell)
Dim CellBounds As 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 Then
' Draw the cell border only if the CellBorderStyle is not None
g.DrawRectangle(TheLinePen, CurrentX, CurrentY, ColumnWidth, RowsHeight(CurrentRow))
End If
CurrentX += ColumnWidth
Next
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 CInt(CurrentY) > (PageHeight - TopMargin - BottomMargin) Then
CurrentRow += 1
Return True
End If
End If
CurrentRow += 1
End While
CurrentRow = 0
mColumnPoint += 1
' Continue to print the next group of columns
If mColumnPoint = mColumnPoints.Count Then
' Which means all columns are printed
mColumnPoint = 0
If Pages < PageNumber Then Pages = PageNumber
PageNumber = 0
mStart = False
Return False
Else
Return True
End If
End Function
' The method that calls all other functions
Public Function DrawDataGridView(ByVal g As Graphics) As Boolean
Try
Calculate(g)
DrawHeader(g)
Dim bContinue As Boolean = DrawRows(g)
Return bContinue
Catch ex As Exception
MessageBox.Show("Operation failed: " & ex.Message.ToString(), Application.ProductName & " - Error", MessageBoxButtons.OK, MessageBoxIcon.[Error])
Return False
End Try
End Function
End Class
End Class
|
|
|
|
|
Thanks for the code.
But one major problem occured in one of my grid. The last column of the grid prints as first column. please solve the problem.
|
|
|
|
|
There's a bug with Win7 64 bit for the lines:
If Not .ShowDialog = DialogResult.OK Then Exit Sub
Where you never see the dialog at all.
To fix this, on the line before add:
.UseEXDialog = True
|
|
|
|
|
This is working great. I translated the original into VB.Net but was unable to get it to work. All I got were blank pages. This works.
But... I am having a minor problem. The text in my column headers is a lot longer than what is in the grid cells below. Consequently I'm only getting part of the header text. The remainder is omitted. It is showing all columns, though. Any idea what I may have done wrong or how to correct the issue. Any help will be greatly appreciated.
Thank you.
|
|
|
|
|
how to print DataGridView Data With FitToPage Style
|
|
|
|
|