Home » SQL ServerRSS

Printing DatagridView

Hi,

I'd like to print only certain columns of a DataGridView. How would something like this be done? I couldn't find any code examples.

Thanks
 

121 Answers Found

 

Answer 1

Hi,

if you want to print not only the cell contents but the ALL the cell settings (most especially the cell background color

in the code of  Forkbeard you just add the follwing:

 

Private Sub Printdoc_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDoc.PrintPage
...............................

...............................

 

 For Each oCell As DataGridViewCell In oRow.Cells

  If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then
................................

 

                   e.Graphics.FillRectangle(New SolidBrush(oCell.InheritedStyle.BackColor), CSng(oColumnLefts(i)), nTop, CSng(oColumnWidths(i)), nHeight)

paste the above in each if

 

Answer 2

Hi guys, I have a problem in this lines

If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then

this is the error

{"El índice estaba fuera del intervalo. Debe ser un valor no negativo e inferior al tamaño de la colección. Nombre del parámetro: index"}

 

if somebody help me, I appreciate.

Thanks

 

Answer 3

el Billy change this  Do While nRowPos < DataGridViewToPrint.Rows.Count with this Do While nRowPos < DataGridViewToPrint.Rows.Count - 1
 

Answer 4

I want to know how I can call this code.

Call PrintDocument1_BeginPrint(sender, e)???

 

Answer 5

in any button

document1.print

in fact if you have the correct imports at the top just ouside the class declaration you should see a list

of items when you type document1 followed by a dot (document1.)

 

Answer 6

ok the following :
1-have CoNNect fix "no print  last row"
2- print only VISIBLE columns


Private oStringFormat As StringFormat
Private oStringFormatComboBox As StringFormat
Private oButton As Button
Private oCheckbox As CheckBox
Private oComboBox As ComboBox

Private nTotalWidth As Int16
Private nRowPos As Int16
Private NewPage As Boolean
Private nPageNo As Int16
Private Header As String = "Header Test"
Private sUserName As String = "Will"

Private Sub PrintDocument1_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.BeginPrint

oStringFormat = New StringFormat
oStringFormat.Alignment = StringAlignment.Near
oStringFormat.LineAlignment = StringAlignment.Center
oStringFormat.Trimming = StringTrimming.EllipsisCharacter

oStringFormatComboBox = New StringFormat
oStringFormatComboBox.LineAlignment = StringAlignment.Center
oStringFormatComboBox.FormatFlags = StringFormatFlags.NoWrap
oStringFormatComboBox.Trimming = StringTrimming.EllipsisCharacter

oButton = New Button
oCheckbox = New CheckBox
oComboBox = New ComboBox

nTotalWidth = 0
For Each oColumn As DataGridViewColumn In DataGridView1.Columns
If oColumn.Visible = True Then
nTotalWidth += oColumn.Width
End If

Next
nPageNo = 1
NewPage = True
nRowPos = 0

End Sub

Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage

Static oColumnLefts As New ArrayList
Static oColumnWidths As New ArrayList
Static oColumnTypes As New ArrayList
Static nHeight As Int16

Dim nWidth, i, nRowsPerPage As Int16
Dim nTop As Int16 = e.MarginBounds.Top
Dim nLeft As Int16 = e.MarginBounds.Left

If nPageNo = 1 Then

For Each oColumn As DataGridViewColumn In DataGridView1.Columns
If oColumn.Visible = True Then
nWidth = CType(Math.Floor(oColumn.Width / nTotalWidth * nTotalWidth * (e.MarginBounds.Width / nTotalWidth)), Int16)

nHeight = e.Graphics.MeasureString(oColumn.HeaderText, oColumn.InheritedStyle.Font, nWidth).Height + 11

oColumnLefts.Add(nLeft)
oColumnWidths.Add(nWidth)
oColumnTypes.Add(oColumn.GetType)
nLeft += nWidth
End If
Next

End If

Do While nRowPos < DataGridView1.Rows.Count - 1

Dim oRow As DataGridViewRow = DataGridView1.Rows(nRowPos)

If nTop + nHeight >= e.MarginBounds.Height + e.MarginBounds.Top Then

DrawFooter(e, nRowsPerPage)

NewPage = True
nPageNo += 1
e.HasMorePages = True
Exit Sub

Else

If NewPage Then

' Draw Header
e.Graphics.DrawString(Header, New Font(DataGridView1.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top - e.Graphics.MeasureString(Header, New Font(DataGridView1.Font, FontStyle.Bold), e.MarginBounds.Width).Height - 13)

' Draw Columns
nTop = e.MarginBounds.Top
i = 0
For Each oColumn As DataGridViewColumn In DataGridView1.Columns
If oColumn.Visible = True Then
e.Graphics.FillRectangle(New SolidBrush(Drawing.Color.LightGray), New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
e.Graphics.DrawString(oColumn.HeaderText, oColumn.InheritedStyle.Font, New SolidBrush(oColumn.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)
i += 1
End If

Next
NewPage = False

End If

nTop += nHeight
i = 0
For Each oCell As DataGridViewCell In oRow.Cells
If oCell.Visible = True Then
If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then

e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)

ElseIf oColumnTypes(i) Is GetType(DataGridViewButtonColumn) Then

oButton.Text = oCell.Value.ToString
oButton.Size = New Size(oColumnWidths(i), nHeight)
Dim oBitmap As New Bitmap(oButton.Width, oButton.Height)
oButton.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))

ElseIf oColumnTypes(i) Is GetType(DataGridViewCheckBoxColumn) Then

oCheckbox.Size = New Size(14, 14)
oCheckbox.Checked = CType(oCell.Value, Boolean)
Dim oBitmap As New Bitmap(oColumnWidths(i), nHeight)
Dim oTempGraphics As Graphics = Graphics.FromImage(oBitmap)
oTempGraphics.FillRectangle(Brushes.White, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
oCheckbox.DrawToBitmap(oBitmap, New Rectangle(CType((oBitmap.Width - oCheckbox.Width) / 2, Int32), CType((oBitmap.Height - oCheckbox.Height) / 2, Int32), oCheckbox.Width, oCheckbox.Height))
e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))

ElseIf oColumnTypes(i) Is GetType(DataGridViewComboBoxColumn) Then

oComboBox.Size = New Size(oColumnWidths(i), nHeight)
Dim oBitmap As New Bitmap(oComboBox.Width, oComboBox.Height)
oComboBox.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i) + 1, nTop, oColumnWidths(i) - 16, nHeight), oStringFormatComboBox)

ElseIf oColumnTypes(i) Is GetType(DataGridViewImageColumn) Then

Dim oCellSize As Rectangle = New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight)
Dim oImageSize As Size = CType(oCell.Value, Image).Size
e.Graphics.DrawImage(oCell.Value, New Rectangle(oColumnLefts(i) + CType(((oCellSize.Width - oImageSize.Width) / 2), Int32), nTop + CType(((oCellSize.Height - oImageSize.Height) / 2), Int32), CType(oCell.Value, Image).Width, CType(oCell.Value, Image).Height))

End If

e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))

i += 1
End If
Next

End If

nRowPos += 1
nRowsPerPage += 1

Loop

DrawFooter(e, nRowsPerPage)

e.HasMorePages = False

End Sub

Private Sub DrawFooter(ByVal e As System.Drawing.Printing.PrintPageEventArgs, ByVal RowsPerPage As Int32)

Dim sPageNo As String = nPageNo.ToString + " of " + Math.Ceiling(DataGridView1.Rows.Count / RowsPerPage).ToString

' Right Align - User Name
e.Graphics.DrawString(sUserName, DataGridView1.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, DataGridView1.Font, e.MarginBounds.Width).Width), e.MarginBounds.Top + e.MarginBounds.Height + 7)

' Left Align - Date/Time
e.Graphics.DrawString(Now.ToLongDateString + " " + Now.ToShortTimeString, DataGridView1.Font, Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top + e.MarginBounds.Height + 7)

' Center - Page No. Info
e.Graphics.DrawString(sPageNo, DataGridView1.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, DataGridView1.Font, e.MarginBounds.Width).Width) / 2, e.MarginBounds.Top + e.MarginBounds.Height + 31)

End Sub
 

Answer 7

yababer, thank you for your post, I like being able to call PrintFactory.Print() to print  the dataGridView. I was having some problems with your code  and have fixed them. The things that I improved were

1. Don't print columns  that are not set to visible
2. Fixed the page numbers
3. Added the ability to print in Landscape

I can view the document in print preview but when I press the print button in print preview it does not print the datagridview. If anyone can fix this please let me know.

To implement create a class called PrintFactory and copy the code below into the class. To print use  
PrintFactory.Print(Me.DataGridView1, "Username", "Header", "L") the "L" will print in landscape, any other text string will print in portrait.
Print Preview
PrintFactory.Preview(Me.DataGridView1, "Username", "Header", "L")

Imports System.Windows.Forms
Public Class PrintFactory
#Region "Instance"

#Region "Declerations"

Private WithEvents _printDocument As Printing.PrintDocument = New Printing.PrintDocument()
Private _dgv As datagridview  
Private _stringFormat As StringFormat
Private _stringFormatComboBox As StringFormat
Private _button As Button
Private _checkBox As CheckBox
Private _comboBox As ComboBox
Private _totalWidth As Int16
Private _rowPos As Int16
Private _newPage As Boolean
Private _pageNumber As Int16
Private _userName As String
Private _headerText As String
Private _blnGotNumPages As Boolean
Private _strNumOfPages As String
Private _orientation As String

#End Region

#Region "Properties"

Private ReadOnly Property DGV() As DataGridView
Get
Return _dgv
End Get
End Property

Private Property HeaderText() As String
Get
Return _headerText
End Get

Set(ByVal value As String)
_headerText = value
End Set

End Property

Private Property UserName() As String

Get
Return _userName
End Get

Set(ByVal value As String)
_userName = value
End Set
End Property

Private Property StringFormat() As StringFormat
Get
Return _stringFormat
End Get

Set(ByVal value As StringFormat)
_stringFormat = value
End Set
End Property

Private Property StringFormatComboBox() As StringFormat
Get
Return _stringFormatComboBox
End Get

Set(ByVal value As StringFormat)
_stringFormatComboBox = value
End Set
End Property

Private Property Button() As Button

Get
Return _button
End Get

Set(ByVal value As Button)
_button = value
End Set
End Property

Private Property CheckBox() As CheckBox
Get
Return _checkBox
End Get

Set(ByVal value As CheckBox)
_checkBox = value
End Set
End Property

Private Property ComboBox() As ComboBox
Get
Return _comboBox
End Get

Set(ByVal value As ComboBox)
_comboBox = value
End Set
End Property

Private Property TotalWidth() As Int16
Get
Return _totalWidth
End Get

Set(ByVal value As Int16)
_totalWidth = value
End Set
End Property

Private Property RowPos() As Int16
Get
Return _rowPos
End Get

Set(ByVal value As Int16)
_rowPos = value
End Set
End Property

Private Property NewPage() As Boolean
Get
Return _newPage
End Get

Set(ByVal value As Boolean)
_newPage = value
End Set
End Property

Private Property PageNumber() As Int16
Get
Return _pageNumber
End Get

Set(ByVal value As Int16)
_pageNumber = value
End Set
End Property
Private Property strNumOfPages() As String
Get
Return _strNumOfPages
End Get

Set(ByVal value As String)
_strNumOfPages = value
End Set
End Property
Private Property blnGotNumPages() As Boolean
Get
Return _blnGotNumPages
End Get

Set(ByVal value As Boolean)
_blnGotNumPages = value
End Set
End Property
Private Property orientation() As String

Get
Return _orientation
End Get

Set(ByVal value As String)
_orientation = value
End Set
End Property
#End Region

Private Sub New(ByVal userName As String, ByVal headerText As String)
Me._userName = userName
Me._headerText = headerText
End Sub

Private Sub _printDocument_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles _printDocument.PrintPage
EndPrint(Me, e)
End Sub

#End Region

#Region "Statics"

Public Shared Function Print(ByVal dgv As DataGridView, ByVal userName As String, ByVal headerText As String, ByVal Orientation As String) As Boolean
Validate(dgv, userName, headerText)
Dim tempPrintFactory As PrintFactory
tempPrintFactory = BeginPrint(dgv, userName, headerText)
If orientation = "L" Then
tempPrintFactory._printDocument.DefaultPageSettings.Landscape = True
End If
tempPrintFactory._printDocument.Print()
End Function

Public Shared Function Preview(ByVal dgv As DataGridView, ByVal userName As String, ByVal headerText As String, ByVal Orientation As String) As Boolean
Validate(dgv, userName, headerText)
Dim tempPrintFactory As PrintFactory
tempPrintFactory = BeginPrint(dgv, userName, headerText)
If Orientation = "L" Then
tempPrintFactory._printDocument.DefaultPageSettings.Landscape = True
End If
Dim tempPrintDiag As New PrintPreviewDialog()
tempPrintDiag.Document = tempPrintFactory._printDocument
tempPrintDiag.ShowDialog()
End Function

Private Shared Function BeginPrint(ByVal dgv As DataGridView, ByVal userName As String, ByVal headerText As String) As PrintFactory
Dim printEntity As PrintFactory = New PrintFactory(userName, headerText)
printEntity._dgv = dgv
printEntity.StringFormat = New StringFormat
printEntity.StringFormat.Alignment = StringAlignment.Near
printEntity.StringFormat.LineAlignment = StringAlignment.Center
printEntity.StringFormat.Trimming = StringTrimming.EllipsisCharacter
printEntity.StringFormatComboBox = New StringFormat
printEntity.StringFormatComboBox.LineAlignment = StringAlignment.Center
printEntity.StringFormatComboBox.FormatFlags = StringFormatFlags.NoWrap
printEntity.StringFormatComboBox.Trimming = StringTrimming.EllipsisCharacter
printEntity.Button = New Button
printEntity.CheckBox = New CheckBox
printEntity.ComboBox = New ComboBox
printEntity.TotalWidth = 0

For Each oColumn As DataGridViewColumn In dgv.Columns
printEntity.TotalWidth += oColumn.Width
Next
printEntity.PageNumber = 1
printEntity.NewPage = True
printEntity.RowPos = 0
Return printEntity
End Function

Private Shared Function EndPrint(ByVal printEntity As PrintFactory, ByVal e As System.Drawing.Printing.PrintPageEventArgs) As Boolean
Static oColumnLefts As New ArrayList
Static oColumnWidths As New ArrayList
Static oColumnTypes As New ArrayList
Static nHeight As Int16

Dim nWidth, i, nRowsPerPage As Int16
Dim blnGotNumPages As Boolean
Dim strNumOfPages As String

Dim nTop As Int16 = e.MarginBounds.Top
Dim nLeft As Int16 = e.MarginBounds.Left

If printEntity.PageNumber = 1 Then

For Each oColumn As DataGridViewColumn In printEntity.DGV.Columns
If oColumn.Visible = True Then
nWidth = CType(Math.Floor(oColumn.Width / printEntity.TotalWidth * printEntity.TotalWidth * (e.MarginBounds.Width / printEntity.TotalWidth)), Int16)
nHeight = e.Graphics.MeasureString(oColumn.HeaderText, oColumn.InheritedStyle.Font, nWidth).Height + 11
oColumnLefts.Add(nLeft)
oColumnWidths.Add(nWidth)
oColumnTypes.Add(oColumn.GetType)
nLeft += nWidth
End If
Next
End If

Do While printEntity.RowPos < printEntity.DGV.Rows.Count
Dim oRow As DataGridViewRow = printEntity.DGV.Rows(printEntity.RowPos)

If nTop + nHeight >= e.MarginBounds.Height + e.MarginBounds.Top Then
DrawFooter(blnGotNumPages, strNumOfPages, printEntity.DGV, printEntity, nRowsPerPage, e)
printEntity.NewPage = True
printEntity.PageNumber += 1
e.HasMorePages = True
Exit Function
Else

If printEntity.NewPage Then

' Draw Header
e.Graphics.DrawString(printEntity.HeaderText, New Font(printEntity.DGV.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top - e.Graphics.MeasureString(printEntity.HeaderText, New Font(printEntity.DGV.Font, FontStyle.Bold), e.MarginBounds.Width).Height - 13)
' Draw Columns
nTop = e.MarginBounds.Top
i = 0
For Each oColumn As DataGridViewColumn In printEntity.DGV.Columns

If oColumn.Visible = True Then
e.Graphics.FillRectangle(New SolidBrush(Drawing.Color.LightGray), New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
e.Graphics.DrawString(oColumn.HeaderText, oColumn.InheritedStyle.Font, New SolidBrush(oColumn.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), printEntity.StringFormat)
i += 1
End If

Next

printEntity.NewPage = False
End If

nTop += nHeight
i = 0

For Each oCell As DataGridViewCell In oRow.Cells
If oCell.Visible = True Then
If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then
e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), printEntity.StringFormat)
ElseIf oColumnTypes(i) Is GetType(DataGridViewButtonColumn) Then
printEntity.Button.Text = oCell.Value.ToString
printEntity.Button.Size = New Size(oColumnWidths(i), nHeight)
Dim oBitmap As New Bitmap(printEntity.Button.Width, printEntity.Button.Height)
printEntity.Button.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
ElseIf oColumnTypes(i) Is GetType(DataGridViewCheckBoxColumn) Then
printEntity.CheckBox.Size = New Size(14, 14)
printEntity.CheckBox.Checked = CType(oCell.Value, Boolean)
Dim oBitmap As New Bitmap(oColumnWidths(i), nHeight)
Dim oTempGraphics As Graphics = Graphics.FromImage(oBitmap)
oTempGraphics.FillRectangle(Brushes.White, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
printEntity.CheckBox.DrawToBitmap(oBitmap, New Rectangle(CType((oBitmap.Width - printEntity.CheckBox.Width) / 2, Int32), CType((oBitmap.Height - printEntity.CheckBox.Height) / 2, Int32), printEntity.CheckBox.Width, printEntity.CheckBox.Height))
e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
ElseIf oColumnTypes(i) Is GetType(DataGridViewComboBoxColumn) Then
printEntity.ComboBox.Size = New Size(oColumnWidths(i), nHeight)
Dim oBitmap As New Bitmap(printEntity.ComboBox.Width, printEntity.ComboBox.Height)
printEntity.ComboBox.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i) + 1, nTop, oColumnWidths(i) - 16, nHeight), printEntity.StringFormatComboBox)
ElseIf oColumnTypes(i) Is GetType(DataGridViewImageColumn) Then
Dim oCellSize As Rectangle = New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight)
Dim oImageSize As Size = CType(oCell.Value, Image).Size

e.Graphics.DrawImage(oCell.Value, New Rectangle(oColumnLefts(i) + CType(((oCellSize.Width - oImageSize.Width) / 2), Int32), nTop + CType(((oCellSize.Height - oImageSize.Height) / 2), Int32), CType(oCell.Value, Image).Width, CType(oCell.Value, Image).Height))
End If
e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
i += 1
End If
Next
End If

printEntity.RowPos += 1
nRowsPerPage += 1

Loop

DrawFooter(blnGotNumPages, strNumOfPages, printEntity.DGV, printEntity, nRowsPerPage, e)
e.HasMorePages = False
End Function
Private Shared Function DrawFooter(ByVal blnGotNumPages As Boolean, ByVal strNumOfPages As String, ByVal dgv As DataGridView, ByVal printEntity As PrintFactory, ByVal RowsPerPage As Int32, ByVal e As System.Drawing.Printing.PrintPageEventArgs) As Boolean
Dim sPageNo As String

If printEntity.blnGotNumPages = False Then
printEntity.blnGotNumPages = True
printEntity.strNumOfPages = Math.Ceiling(dgv.Rows.Count / RowsPerPage).ToString
sPageNo = printEntity.PageNumber.ToString + " of " + Math.Ceiling(dgv.Rows.Count / RowsPerPage).ToString
Else
sPageNo = printEntity.PageNumber.ToString + " of " + printEntity.strNumOfPages
End If

' Right Align - User Name
e.Graphics.DrawString(printEntity.UserName, dgv.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(printEntity.UserName, dgv.Font, e.MarginBounds.Width).Width), e.MarginBounds.Top + e.MarginBounds.Height + 7)
' Left Align - Date/Time
e.Graphics.DrawString(Now.ToLongDateString + " " + Now.ToShortTimeString, dgv.Font, Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top + e.MarginBounds.Height + 7)
' Center - Page No. Info
e.Graphics.DrawString(sPageNo, dgv.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, dgv.Font, e.MarginBounds.Width).Width) / 2, e.MarginBounds.Top + e.MarginBounds.Height + 31)
End Function

Private Shared Sub Validate(ByVal dgv As DataGridView, ByVal userName As String, ByVal headerText As String)
If dgv Is Nothing Then
Throw New ArgumentNullException("dgv")
End If
If String.IsNullOrEmpty(userName) = True Then
Throw New ArgumentNullException("userName")
End If
If String.IsNullOrEmpty(headerText) = True Then
Throw New ArgumentNullException("headerText")
End If
End Sub
#End Region
End Class
 

Answer 8

As I have had the same problem printing  the contents of a DataGridView, I appreciate all the fine suggestions of all those who have responded to this post. However, I have the further problem of having to print  not only the cell contents but the ALL the cell settings (most especially the cell background color) in my DataGridView.

Also, I need to print out the text in the RowHeader cells.

Would appreciate any help in this area.

Thanks Profusely,
EdYberg
 

Answer 9

I figured out how to print  out my Row Headers and all the DGV Cell Formatting Contents using  AlexWA's fine PrintFactory Class code.

Along the way I discovered that by checking the Visible property of the column, you are also checking to see whether or not your column is visible in the underlying DataGridView control which means that if you have horizontal scrollbars showing (meaning that some columns  are NOT visible due to the fact that they are not showing rather than because a user has SET then to Visible = False) those columns that are hidden by the size of the grid control will not print either. BTW, AlexWA asked why his code  would not print out the first page of his grid and that is because he set the page to 1 in his BeginPrint Sub, so that by the time he gets to printing  out the grid contents he is already on Page 2 and since there is no data yet for Page 2, he just prints out a blank Page 2 and he's done. Not quite sure why that happens but setting the Page to 0 in the BeginPrint Sub fixes the problem.

Thanks again to AlexWA!

(I'm sorry I can't show the code for this because I am not at my development machine right now, but if you reply to this post, I will reply with the code that I came up with.)

The problem I am now grappling with is how to print out more than 40 columns (in Landscape) by somehow capturing the total number of columns and dividing the TotalWidth by that to set the column widths...  not having much success... seems that the columns just start out again at the beginning of the grid and overwrite the previous contents.
 

Answer 10

Thanks a lot guys the code  is amazing..
 

Answer 11

Hello.
Can you tell me why I'm getting in my printed paper date format like : 8.8.2009 0:00:00 ?
In my datagridview  there is no time at the end, but on printed paper there is. I would like to remove that time from the end, so what exactly in this code  should i change to do that ?
Thank you in advance.
 

Answer 12

Find the place in your code  where it says... ' Left Align - Date/Time e.Graphics.DrawString(Now.ToLongDateString + " " + Now.ToShortTimeString, dgv.Font, Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top + e.MarginBounds.Height + 7) ...this is the code that's printing  your footer. You could try commenting it out. Good luck!
 

Answer 13

EdYberg thank you for your reply and i apologize for not being clear about my problem, but i will try to explain a little better this time.
I'm not having problem with time at the end (bottom) of the printed paper, but i'm having problems with time in columns  that have date value .
In datagridview  there's correct date and there's no time after the date, but when i print  it (on paper) there is time and it says "0:00:00". something like :

| _____date_____  |
|                           |
| 8.8.2009 0:00:00 |
| 4.4.2009 0:00:00 |
| 2.6.2009 0:00:00 |

Also in access table that column i set to short date and there's just date (no time).
My English is not very good but i hope i explained myself a little better this time.
Any kind of help will be very appreciated.

 

Answer 14

Hi Will-affinity

your code  works great but the document is being printed on the right of the page  and no footer,  this hapends on a DGV that is bindet by code, if i use a DGV and Bind it by smart tag it works fine. is there a fix for this>
If i can make the default layout to Landscape that will do


thanks

 

Answer 15

Thanks so much for this routine.  I was printing  pages on top of each other and about to pull my hair out.  This routine you posted works great, even better than I expected with very little work needed to insert into my project.  I realize it is three years old but it still works great in VBE2008
 

Answer 16

hi there, i'm new here.. i've tried your codes and it's great but i want to print  something on the last page like "NOTHING FOLLOWS", i really dont know where to put the DrawString thing here.. all i want to to do is to print something on the last page.. could you help me??
 

Answer 17

hi there Nectuss.. that's great i have tried it, and my printing  now is working properly, the last record on the DataGridView is now recognized.. and the records don't overlap with the footer.. btw, can you help with the printing of text or string on the last page of the reports.. i just dont know where to put the draw string thing, i want to some text like "NOTHING FOLLOWS".. on the last part of the page.. plz help me.. im hoping for your response..
 

Answer 18

[i][i][i][i]
 

Answer 19

hi there, im new here, i want to know how to print  some string after the datagridview  contents, like i want to print the "NOTHING FOLLOWS", or even "Total Nos. of Records", something like that, i want to know how to, pls help me guyz..
 

Answer 20

hi there, i wanted to know how to print  some label or string after printing  the contents of the datagridview, like for example i wanted to print the total no. of records in the datagridview  table that has been printed or like i wanted to print "NOTHING FOLLOWS" after the printing of the records, i wanted to place them after the last record that was printed, ive been working on it lately but it seems that i really cant do it, could you help me out here?
 

Answer 21

hi there, i wanted to know how to print  some label or string after printing  the contents of the datagridview, like for example i wanted to print the total no. of records in the datagridview  table that has been printed or like i wanted to print "NOTHING FOLLOWS" after the printing of the records, i wanted to place them after the last record that was printed, ive been working on it lately but it seems that i really cant do it, could you help me out here?
 

Answer 22

Private oStringFormat As StringFormat
    Private oStringFormatComboBox As StringFormat
    Private oButton As Button
    Private oCheckbox As CheckBox
    Private oComboBox As ComboBox

    Private nTotalWidth As Int16
    Private nRowPos As Int16
    Private NewPage As Boolean
    Private nPageNo As Int16
    Private Header As String = "Header Test"
    Private sUserName As String = "Will"

    Private Sub PrintDocument1_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.BeginPrint

        oStringFormat = New StringFormat
        oStringFormat.Alignment = StringAlignment.Near
        oStringFormat.LineAlignment = StringAlignment.Center
        oStringFormat.Trimming = StringTrimming.EllipsisCharacter

        oStringFormatComboBox = New StringFormat
        oStringFormatComboBox.LineAlignment = StringAlignment.Center
        oStringFormatComboBox.FormatFlags = StringFormatFlags.NoWrap
        oStringFormatComboBox.Trimming = StringTrimming.EllipsisCharacter

        oButton = New Button
        oCheckbox = New CheckBox
        oComboBox = New ComboBox

        nTotalWidth = 0
        For Each oColumn As DataGridViewColumn In DataGridView1.Columns

            nTotalWidth += oColumn.Width

        Next
        nPageNo = 1
        NewPage = True
        nRowPos = 0

    End Sub

    Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage

            Static oColumnLefts As New ArrayList
            Static oColumnWidths As New ArrayList
            Static oColumnTypes As New ArrayList
            Static nHeight As Int16

            Dim nWidth, i, nRowsPerPage As Int16
            Dim nTop As Int16 = e.MarginBounds.Top
            Dim nLeft As Int16 = e.MarginBounds.Left

            If nPageNo = 1 Then

                For Each oColumn As DataGridViewColumn In DataGridView1.Columns

                    nWidth = CType(Math.Floor(oColumn.Width / nTotalWidth * nTotalWidth * (e.MarginBounds.Width / nTotalWidth)), Int16)

                    nHeight = e.Graphics.MeasureString(oColumn.HeaderText, oColumn.InheritedStyle.Font, nWidth).Height + 11

                    oColumnLefts.Add(nLeft)
                    oColumnWidths.Add(nWidth)
                    oColumnTypes.add(oColumn.GetType)
                    nLeft += nWidth

                Next

            End If

            Do While nRowPos < DataGridView1.Rows.Count - 1

                Dim oRow As DataGridViewRow = DataGridView1.Rows(nRowPos)

                If nTop + nHeight >= e.MarginBounds.Height + e.MarginBounds.Top Then

                    DrawFooter(e, nRowsPerPage)

                    NewPage = True
                    nPageNo += 1
                    e.HasMorePages = True
                    Exit Sub

                Else

                    If NewPage Then

                        ' Draw Header
                        e.Graphics.DrawString(Header, New Font(DataGridView1.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top - e.Graphics.MeasureString(Header, New Font(DataGridView1.Font, FontStyle.Bold), e.MarginBounds.Width).Height - 13)

                        ' Draw Columns
                        nTop = e.MarginBounds.Top
                        i = 0
                        For Each oColumn As DataGridViewColumn In DataGridView1.Columns

                            e.Graphics.FillRectangle(New SolidBrush(Drawing.Color.LightGray), New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
                            e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
                            e.Graphics.DrawString(oColumn.HeaderText, oColumn.InheritedStyle.Font, New SolidBrush(oColumn.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)
                            i += 1

                        Next
                        NewPage = False

                    End If

                    nTop += nHeight
                    i = 0
                    For Each oCell As DataGridViewCell In oRow.Cells

                        If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then

                            e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)

                        ElseIf oColumnTypes(i) Is GetType(DataGridViewButtonColumn) Then

                            oButton.Text = oCell.Value.ToString
                            oButton.Size = New Size(oColumnWidths(i), nHeight)
                            Dim oBitmap As New Bitmap(oButton.Width, oButton.Height)
                            oButton.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
                            e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))

                        ElseIf oColumnTypes(i) Is GetType(DataGridViewCheckBoxColumn) Then

                            oCheckbox.Size = New Size(14, 14)
                            oCheckbox.Checked = CType(oCell.Value, Boolean)
                            Dim oBitmap As New Bitmap(oColumnWidths(i), nHeight)
                            Dim oTempGraphics As Graphics = Graphics.FromImage(oBitmap)
                            oTempGraphics.FillRectangle(Brushes.White, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
                            oCheckbox.DrawToBitmap(oBitmap, New Rectangle(CType((oBitmap.Width - oCheckbox.Width) / 2, Int32), CType((oBitmap.Height - oCheckbox.Height) / 2, Int32), oCheckbox.Width, oCheckbox.Height))
                            e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))

                        ElseIf oColumnTypes(i) Is GetType(DataGridViewComboBoxColumn) Then

                            oComboBox.Size = New Size(oColumnWidths(i), nHeight)
                            Dim oBitmap As New Bitmap(oComboBox.Width, oComboBox.Height)
                            oComboBox.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
                            e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
                            e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i) + 1, nTop, oColumnWidths(i) - 16, nHeight), oStringFormatComboBox)

                        ElseIf oColumnTypes(i) Is GetType(DataGridViewImageColumn) Then

                            Dim oCellSize As Rectangle = New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight)
                            Dim oImageSize As Size = CType(oCell.Value, Image).Size
                            e.Graphics.DrawImage(oCell.Value, New Rectangle(oColumnLefts(i) + CType(((oCellSize.Width - oImageSize.Width) / 2), Int32), nTop + CType(((oCellSize.Height - oImageSize.Height) / 2), Int32), CType(oCell.Value, Image).Width, CType(oCell.Value, Image).Height))

                        End If

                        e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))

                        i += 1

                    Next

                End If

                nRowPos += 1
                nRowsPerPage += 1

            Loop

            DrawFooter(e, nRowsPerPage)

            e.HasMorePages = False

    End Sub

    Private Sub DrawFooter(ByVal e As System.Drawing.Printing.PrintPageEventArgs, ByVal RowsPerPage As Int32)

        Dim sPageNo As String = nPageNo.ToString + " of " + Math.Ceiling(DataGridView1.Rows.Count / RowsPerPage).ToString

        ' Right Align - User Name
        e.Graphics.DrawString(sUserName, DataGridView1.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, DataGridView1.Font, e.MarginBounds.Width).Width), e.MarginBounds.Top + e.MarginBounds.Height + 7)

        ' Left Align - Date/Time
        e.Graphics.DrawString(Now.ToLongDateString + " " + Now.ToShortTimeString, DataGridView1.Font, Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top + e.MarginBounds.Height + 7)

        ' Center  - Page No. Info
        e.Graphics.DrawString(sPageNo, DataGridView1.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, DataGridView1.Font, e.MarginBounds.Width).Width) / 2, e.MarginBounds.Top + e.MarginBounds.Height + 31)

    End Sub


hi there, i wanted to know how to print  some label or string after printing  the contents of the datagridview, like for example i wanted to print the total no. of records in the datagridview  table that has been printed or like i wanted to print "NOTHING FOLLOWS" after the printing of the records, i wanted to place them after the last record that was printed, ive been working on it lately but it seems that i really cant do it, could you help me out here?
 

Answer 23

There's a problem with printing  out the footer. It messes up the page number if the page has fewer than the max number of rows. For example, I had 38 rows spread over two pages, the first page said "Page 1 of 2" but the last one would say "Page 2 of 13" since there were only 3 rows on the final page. Either way, I've 'Option Stricted' and turned it into a class unto itself. Enjoy!

To Implement:
    Private Sub btnPrintPreview_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPrintPreview.Click
        If IsNothing(Printer) Then
            Printer = New Printer(dgvJobs, Me.Text, gblUserName) 'DataGridView, Wiindow Title (as the Page Header), Username
        End If
        Printer.ShowPrintPreviewDialog()
    End Sub

    Private Sub btnPrint_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPrint.Click
        If IsNothing(Printer) Then
            Printer = New Printer(dgvJobs, Me.Text, gblUserName) 'DataGridView, Wiindow Title (as the Page Header), Username
        End If
        Printer.Print()
    End Sub

Public Class Printer
    Private oStringFormat As StringFormat
    Private oStringFormatComboBox As StringFormat
    Private oButton As Button
    Private oCheckbox As CheckBox
    Private oComboBox As ComboBox

    Private nTotalWidth As Int16
    Private nRowPos As Int16
    Private NewPage As Boolean
    Private nPageNo As Int16
    Private Header As String
    Private sUserName As String
    Private nPageCount As Integer = 0
    Private dgv As DataGridView
    Private WithEvents PrintDoc As New Printing.PrintDocument
    Private storedPageSettings As Printing.PageSettings = New Printing.PageSettings()

    Property DataGridViewToPrint() As DataGridView
        Get
            Return dgv
        End Get
        Set(ByVal value As DataGridView)
            dgv = value
        End Set
    End Property
    Property UserName() As String
        Get
            Return sUserName
        End Get
        Set(ByVal value As String)
            sUserName = value
        End Set
    End Property
    Property HeaderText() As String
        Get
            Return Header
        End Get
        Set(ByVal value As String)
            Header = value
        End Set
    End Property

    Public Sub New(ByVal aDGV As DataGridView, ByVal aHeader As String, ByVal aUserName As String)
        DataGridViewToPrint = aDGV
        UserName = aUserName
        HeaderText = aHeader
    End Sub
    Public Sub Print()
        Dim psDlg As New PageSetupDialog
        psDlg.PageSettings = storedPageSettings
        psDlg.ShowDialog()
    End Sub
    Public Sub ShowPrintPreviewDialog()
        Dim dlg As New PrintPreviewDialog()
        dlg.Document = PrintDoc
        dlg.ShowDialog()
    End Sub
    Private Sub PrintDoc_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDoc.BeginPrint

        oStringFormat = New StringFormat
        oStringFormat.Alignment = StringAlignment.Near
        oStringFormat.LineAlignment = StringAlignment.Center
        oStringFormat.Trimming = StringTrimming.EllipsisCharacter

        oStringFormatComboBox = New StringFormat
        oStringFormatComboBox.LineAlignment = StringAlignment.Center
        oStringFormatComboBox.FormatFlags = StringFormatFlags.NoWrap
        oStringFormatComboBox.Trimming = StringTrimming.EllipsisCharacter

        oButton = New Button
        oCheckbox = New CheckBox
        oComboBox = New ComboBox

        nTotalWidth = 0
        For Each oColumn As DataGridViewColumn In DataGridViewToPrint.Columns

            nTotalWidth = CShort(nTotalWidth + oColumn.Width)

        Next
        nPageNo = 1
        NewPage = True
        nRowPos = 0

    End Sub

    Private Sub Printdoc_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDoc.PrintPage

        Static oColumnLefts As New ArrayList
        Static oColumnWidths As New ArrayList
        Static oColumnTypes As New ArrayList
        Static nHeight As Int16

        Dim nWidth, i, nRowsPerPage As Int16
        Dim nTop As Int16 = CShort(e.MarginBounds.Top)
        Dim nLeft As Int16 = CShort(e.MarginBounds.Left)

        If nPageNo = 1 Then

            For Each oColumn As DataGridViewColumn In DataGridViewToPrint.Columns

                nWidth = CType(Math.Floor(oColumn.Width / nTotalWidth * nTotalWidth * (e.MarginBounds.Width / nTotalWidth)), Int16)

                nHeight = CShort(e.Graphics.MeasureString(oColumn.HeaderText, oColumn.InheritedStyle.Font, nWidth).Height + 11)

                oColumnLefts.Add(nLeft)
                oColumnWidths.Add(nWidth)
                oColumnTypes.Add(oColumn.GetType)
                nLeft += nWidth

            Next

        End If

        Do While nRowPos < DataGridViewToPrint.Rows.Count

            Dim oRow As DataGridViewRow = DataGridViewToPrint.Rows(nRowPos)

            If nTop + nHeight >= e.MarginBounds.Height + e.MarginBounds.Top Then

                DrawFooter(e, nRowsPerPage)

                NewPage = True
                nPageNo = CShort(nPageNo + 1)
                e.HasMorePages = True
                Exit Sub

            Else

                If NewPage Then

                    ' Draw Header
                    e.Graphics.DrawString(Header, New Font(DataGridViewToPrint.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top - e.Graphics.MeasureString(Header, New Font(DataGridViewToPrint.Font, FontStyle.Bold), e.MarginBounds.Width).Height - 13)

                    ' Draw Columns
                    nTop = CShort(e.MarginBounds.Top)
                    i = 0
                    For Each oColumn As DataGridViewColumn In DataGridViewToPrint.Columns

                        e.Graphics.FillRectangle(New SolidBrush(Drawing.Color.LightGray), New Rectangle(CInt(oColumnLefts(i)), nTop, CInt(oColumnWidths(i)), nHeight))
                        e.Graphics.DrawRectangle(Pens.Black, New Rectangle(CInt(oColumnLefts(i)), nTop, CInt(oColumnWidths(i)), nHeight))
                        e.Graphics.DrawString(oColumn.HeaderText, oColumn.InheritedStyle.Font, New SolidBrush(oColumn.InheritedStyle.ForeColor), New RectangleF(CSng(oColumnLefts(i)), nTop, CSng(oColumnWidths(i)), nHeight), oStringFormat)
                        i = CShort(i + 1)

                    Next
                    NewPage = False

                End If

                nTop += nHeight
                i = 0
                For Each oCell As DataGridViewCell In oRow.Cells

                    If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then

                        e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(CSng(oColumnLefts(i)), nTop, CSng(oColumnWidths(i)), nHeight), oStringFormat)

                    ElseIf oColumnTypes(i) Is GetType(DataGridViewButtonColumn) Then

                        oButton.Text = oCell.Value.ToString
                        oButton.Size = New Size(CInt(oColumnWidths(i)), nHeight)
                        Dim oBitmap As New Bitmap(oButton.Width, oButton.Height)
                        oButton.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
                        e.Graphics.DrawImage(oBitmap, New Point(CInt(oColumnLefts(i)), nTop))

                    ElseIf oColumnTypes(i) Is GetType(DataGridViewCheckBoxColumn) Then

                        oCheckbox.Size = New Size(14, 14)
                        oCheckbox.Checked = CType(oCell.Value, Boolean)
                        Dim oBitmap As New Bitmap(CInt(oColumnWidths(i)), nHeight)
                        Dim oTempGraphics As Graphics = Graphics.FromImage(oBitmap)
                        oTempGraphics.FillRectangle(Brushes.White, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
                        oCheckbox.DrawToBitmap(oBitmap, New Rectangle(CType((oBitmap.Width - oCheckbox.Width) / 2, Int32), CType((oBitmap.Height - oCheckbox.Height) / 2, Int32), oCheckbox.Width, oCheckbox.Height))
                        e.Graphics.DrawImage(oBitmap, New Point(CInt(oColumnLefts(i)), nTop))

                    ElseIf oColumnTypes(i) Is GetType(DataGridViewComboBoxColumn) Then

                        oComboBox.Size = New Size(CInt(oColumnWidths(i)), nHeight)
                        Dim oBitmap As New Bitmap(oComboBox.Width, oComboBox.Height)
                        oComboBox.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
                        e.Graphics.DrawImage(oBitmap, New Point(CInt(oColumnLefts(i)), nTop))
                        e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(CInt(oColumnLefts(i)) + 1, nTop, CInt(oColumnWidths(i)) - 16, nHeight), oStringFormatComboBox)

                    ElseIf oColumnTypes(i) Is GetType(DataGridViewImageColumn) Then

                        Dim oCellSize As Rectangle = New Rectangle(CInt(oColumnLefts(i)), nTop, CInt(oColumnWidths(i)), nHeight)
                        Dim oImageSize As Size = CType(oCell.Value, Image).Size
                        e.Graphics.DrawImage(CType(oCell.Value, Image), New Rectangle(CType(oColumnLefts(i), Int32) + CType(((oCellSize.Width - oImageSize.Width) / 2), Int32), nTop + CType(((oCellSize.Height - oImageSize.Height) / 2), Int32), CType(oCell.Value, Image).Width, CType(oCell.Value, Image).Height))

                    End If

                    e.Graphics.DrawRectangle(Pens.Black, New Rectangle(CInt(oColumnLefts(i)), nTop, CInt(oColumnWidths(i)), nHeight))

                    i = CShort(i + 1)

                Next

            End If

            nRowPos = CShort(nRowPos + 1)
            nRowsPerPage = CShort(nRowsPerPage + 1)
        Loop

        DrawFooter(e, nRowsPerPage)

        e.HasMorePages = False

    End Sub

    Private Sub DrawFooter(ByVal e As System.Drawing.Printing.PrintPageEventArgs, ByVal RowsPerPage As Int32)

        'Changed from Page XXX of XXX to just Page XXX because
        'Math.Ceiling(DataGridViewToPrint.Rows.Count / RowsPerPage).ToString() would generate
        'inaccurate page numbers on pages with less than the max number of rows (ie: the last page)
        'Dim sPageNo As String = nPageNo.ToString + " of " + Math.Ceiling(DataGridViewToPrint.Rows.Count / RowsPerPage).ToString
        Dim sPageNo As String = "Page " + nPageNo.ToString

        ' Right Align - User Name
        e.Graphics.DrawString("Printed by: " + sUserName, DataGridViewToPrint.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, DataGridViewToPrint.Font, e.MarginBounds.Width).Width), e.MarginBounds.Top + e.MarginBounds.Height + 7)

        ' Left Align - Date/Time
        e.Graphics.DrawString(Now.ToLongDateString + " " + Now.ToShortTimeString, DataGridViewToPrint.Font, Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top + e.MarginBounds.Height + 7)

        ' Center  - Page No. Info
        e.Graphics.DrawString(sPageNo, DataGridViewToPrint.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, DataGridViewToPrint.Font, e.MarginBounds.Width).Width) / 2, e.MarginBounds.Top + e.MarginBounds.Height + 31)

    End Sub
End Class



hi there, i wanted to know how to print  some label or string after printing the contents of the datagridview, like for example i wanted to print the total no. of records in the datagridview  table that has been printed or like i wanted to print "NOTHING FOLLOWS" after the printing of the records, i wanted to place them after the last record that was printed, ive been working on it lately but it seems that i really cant do it, could you help me out here?
 

Answer 24

Hi,

This code  is absolutely amazing. works exactly the way I want...
However, I have a question:

Can a particular cell be aligned Right ? I looked in the code but could not find  any way to alter the default alignment.
Any help in this regard would be appreciated.

Thanks

Kazmi
 

Answer 25

yababer, thank you for your post, I like being able to call PrintFactory.Print() to print  the dataGridView. I was having some problems with your code  and have fixed them. The things that I improved were

1. Don't print columns  that are not set to visible
2. Fixed the page numbers
3. Added the ability to print in Landscape

I can view the document in print preview but when I press the print button in print preview it does not print the datagridview. If anyone can fix this please let me know.

To implement create a class called PrintFactory and copy the code below into the class. To print use  
PrintFactory.Print(Me.DataGridView1, "Username", "Header", "L") the "L" will print in landscape, any other text string will print in portrait.
Print Preview
PrintFactory.Preview(Me.DataGridView1, "Username", "Header", "L")

Imports System.Windows.Forms
Public Class PrintFactory
#Region "Instance"

#Region "Declerations"

Private WithEvents _printDocument As Printing.PrintDocument = New Printing.PrintDocument()
Private _dgv As datagridview  
Private _stringFormat As StringFormat
Private _stringFormatComboBox As StringFormat
Private _button As Button
Private _checkBox As CheckBox
Private _comboBox As ComboBox
Private _totalWidth As Int16
Private _rowPos As Int16
Private _newPage As Boolean
Private _pageNumber As Int16
Private _userName As String
Private _headerText As String
Private _blnGotNumPages As Boolean
Private _strNumOfPages As String
Private _orientation As String

#End Region

#Region "Properties"

Private ReadOnly Property DGV() As DataGridView
Get
Return _dgv
End Get
End Property

Private Property HeaderText() As String
Get
Return _headerText
End Get

Set(ByVal value As String)
_headerText = value
End Set

End Property

Private Property UserName() As String

Get
Return _userName
End Get

Set(ByVal value As String)
_userName = value
End Set
End Property

Private Property StringFormat() As StringFormat
Get
Return _stringFormat
End Get

Set(ByVal value As StringFormat)
_stringFormat = value
End Set
End Property

Private Property StringFormatComboBox() As StringFormat
Get
Return _stringFormatComboBox
End Get

Set(ByVal value As StringFormat)
_stringFormatComboBox = value
End Set
End Property

Private Property Button() As Button

Get
Return _button
End Get

Set(ByVal value As Button)
_button = value
End Set
End Property

Private Property CheckBox() As CheckBox
Get
Return _checkBox
End Get

Set(ByVal value As CheckBox)
_checkBox = value
End Set
End Property

Private Property ComboBox() As ComboBox
Get
Return _comboBox
End Get

Set(ByVal value As ComboBox)
_comboBox = value
End Set
End Property

Private Property TotalWidth() As Int16
Get
Return _totalWidth
End Get

Set(ByVal value As Int16)
_totalWidth = value
End Set
End Property

Private Property RowPos() As Int16
Get
Return _rowPos
End Get

Set(ByVal value As Int16)
_rowPos = value
End Set
End Property

Private Property NewPage() As Boolean
Get
Return _newPage
End Get

Set(ByVal value As Boolean)
_newPage = value
End Set
End Property

Private Property PageNumber() As Int16
Get
Return _pageNumber
End Get

Set(ByVal value As Int16)
_pageNumber = value
End Set
End Property
Private Property strNumOfPages() As String
Get
Return _strNumOfPages
End Get

Set(ByVal value As String)
_strNumOfPages = value
End Set
End Property
Private Property blnGotNumPages() As Boolean
Get
Return _blnGotNumPages
End Get

Set(ByVal value As Boolean)
_blnGotNumPages = value
End Set
End Property
Private Property orientation() As String

Get
Return _orientation
End Get

Set(ByVal value As String)
_orientation = value
End Set
End Property
#End Region

Private Sub New(ByVal userName As String, ByVal headerText As String)
Me._userName = userName
Me._headerText = headerText
End Sub

Private Sub _printDocument_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles _printDocument.PrintPage
EndPrint(Me, e)
End Sub

#End Region

#Region "Statics"

Public Shared Function Print(ByVal dgv As DataGridView, ByVal userName As String, ByVal headerText As String, ByVal Orientation As String) As Boolean
Validate(dgv, userName, headerText)
Dim tempPrintFactory As PrintFactory
tempPrintFactory = BeginPrint(dgv, userName, headerText)
If orientation = "L" Then
tempPrintFactory._printDocument.DefaultPageSettings.Landscape = True
End If
tempPrintFactory._printDocument.Print()
End Function

Public Shared Function Preview(ByVal dgv As DataGridView, ByVal userName As String, ByVal headerText As String, ByVal Orientation As String) As Boolean
Validate(dgv, userName, headerText)
Dim tempPrintFactory As PrintFactory
tempPrintFactory = BeginPrint(dgv, userName, headerText)
If Orientation = "L" Then
tempPrintFactory._printDocument.DefaultPageSettings.Landscape = True
End If
Dim tempPrintDiag As New PrintPreviewDialog()
tempPrintDiag.Document = tempPrintFactory._printDocument
tempPrintDiag.ShowDialog()
End Function

Private Shared Function BeginPrint(ByVal dgv As DataGridView, ByVal userName As String, ByVal headerText As String) As PrintFactory
Dim printEntity As PrintFactory = New PrintFactory(userName, headerText)
printEntity._dgv = dgv
printEntity.StringFormat = New StringFormat
printEntity.StringFormat.Alignment = StringAlignment.Near
printEntity.StringFormat.LineAlignment = StringAlignment.Center
printEntity.StringFormat.Trimming = StringTrimming.EllipsisCharacter
printEntity.StringFormatComboBox = New StringFormat
printEntity.StringFormatComboBox.LineAlignment = StringAlignment.Center
printEntity.StringFormatComboBox.FormatFlags = StringFormatFlags.NoWrap
printEntity.StringFormatComboBox.Trimming = StringTrimming.EllipsisCharacter
printEntity.Button = New Button
printEntity.CheckBox = New CheckBox
printEntity.ComboBox = New ComboBox
printEntity.TotalWidth = 0

For Each oColumn As DataGridViewColumn In dgv.Columns
printEntity.TotalWidth += oColumn.Width
Next
printEntity.PageNumber = 1
printEntity.NewPage = True
printEntity.RowPos = 0
Return printEntity
End Function

Private Shared Function EndPrint(ByVal printEntity As PrintFactory, ByVal e As System.Drawing.Printing.PrintPageEventArgs) As Boolean
Static oColumnLefts As New ArrayList
Static oColumnWidths As New ArrayList
Static oColumnTypes As New ArrayList
Static nHeight As Int16

Dim nWidth, i, nRowsPerPage As Int16
Dim blnGotNumPages As Boolean
Dim strNumOfPages As String

Dim nTop As Int16 = e.MarginBounds.Top
Dim nLeft As Int16 = e.MarginBounds.Left

If printEntity.PageNumber = 1 Then

For Each oColumn As DataGridViewColumn In printEntity.DGV.Columns
If oColumn.Visible = True Then
nWidth = CType(Math.Floor(oColumn.Width / printEntity.TotalWidth * printEntity.TotalWidth * (e.MarginBounds.Width / printEntity.TotalWidth)), Int16)
nHeight = e.Graphics.MeasureString(oColumn.HeaderText, oColumn.InheritedStyle.Font, nWidth).Height + 11
oColumnLefts.Add(nLeft)
oColumnWidths.Add(nWidth)
oColumnTypes.Add(oColumn.GetType)
nLeft += nWidth
End If
Next
End If

Do While printEntity.RowPos < printEntity.DGV.Rows.Count
Dim oRow As DataGridViewRow = printEntity.DGV.Rows(printEntity.RowPos)

If nTop + nHeight >= e.MarginBounds.Height + e.MarginBounds.Top Then
DrawFooter(blnGotNumPages, strNumOfPages, printEntity.DGV, printEntity, nRowsPerPage, e)
printEntity.NewPage = True
printEntity.PageNumber += 1
e.HasMorePages = True
Exit Function
Else

If printEntity.NewPage Then

' Draw Header
e.Graphics.DrawString(printEntity.HeaderText, New Font(printEntity.DGV.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top - e.Graphics.MeasureString(printEntity.HeaderText, New Font(printEntity.DGV.Font, FontStyle.Bold), e.MarginBounds.Width).Height - 13)
' Draw Columns
nTop = e.MarginBounds.Top
i = 0
For Each oColumn As DataGridViewColumn In printEntity.DGV.Columns

If oColumn.Visible = True Then
e.Graphics.FillRectangle(New SolidBrush(Drawing.Color.LightGray), New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
e.Graphics.DrawString(oColumn.HeaderText, oColumn.InheritedStyle.Font, New SolidBrush(oColumn.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), printEntity.StringFormat)
i += 1
End If

Next

printEntity.NewPage = False
End If

nTop += nHeight
i = 0

For Each oCell As DataGridViewCell In oRow.Cells
If oCell.Visible = True Then
If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then
e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), printEntity.StringFormat)
ElseIf oColumnTypes(i) Is GetType(DataGridViewButtonColumn) Then
printEntity.Button.Text = oCell.Value.ToString
printEntity.Button.Size = New Size(oColumnWidths(i), nHeight)
Dim oBitmap As New Bitmap(printEntity.Button.Width, printEntity.Button.Height)
printEntity.Button.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
ElseIf oColumnTypes(i) Is GetType(DataGridViewCheckBoxColumn) Then
printEntity.CheckBox.Size = New Size(14, 14)
printEntity.CheckBox.Checked = CType(oCell.Value, Boolean)
Dim oBitmap As New Bitmap(oColumnWidths(i), nHeight)
Dim oTempGraphics As Graphics = Graphics.FromImage(oBitmap)
oTempGraphics.FillRectangle(Brushes.White, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
printEntity.CheckBox.DrawToBitmap(oBitmap, New Rectangle(CType((oBitmap.Width - printEntity.CheckBox.Width) / 2, Int32), CType((oBitmap.Height - printEntity.CheckBox.Height) / 2, Int32), printEntity.CheckBox.Width, printEntity.CheckBox.Height))
e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
ElseIf oColumnTypes(i) Is GetType(DataGridViewComboBoxColumn) Then
printEntity.ComboBox.Size = New Size(oColumnWidths(i), nHeight)
Dim oBitmap As New Bitmap(printEntity.ComboBox.Width, printEntity.ComboBox.Height)
printEntity.ComboBox.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i) + 1, nTop, oColumnWidths(i) - 16, nHeight), printEntity.StringFormatComboBox)
ElseIf oColumnTypes(i) Is GetType(DataGridViewImageColumn) Then
Dim oCellSize As Rectangle = New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight)
Dim oImageSize As Size = CType(oCell.Value, Image).Size

e.Graphics.DrawImage(oCell.Value, New Rectangle(oColumnLefts(i) + CType(((oCellSize.Width - oImageSize.Width) / 2), Int32), nTop + CType(((oCellSize.Height - oImageSize.Height) / 2), Int32), CType(oCell.Value, Image).Width, CType(oCell.Value, Image).Height))
End If
e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
i += 1
End If
Next
End If

printEntity.RowPos += 1
nRowsPerPage += 1

Loop

DrawFooter(blnGotNumPages, strNumOfPages, printEntity.DGV, printEntity, nRowsPerPage, e)
e.HasMorePages = False
End Function
Private Shared Function DrawFooter(ByVal blnGotNumPages As Boolean, ByVal strNumOfPages As String, ByVal dgv As DataGridView, ByVal printEntity As PrintFactory, ByVal RowsPerPage As Int32, ByVal e As System.Drawing.Printing.PrintPageEventArgs) As Boolean
Dim sPageNo As String

If printEntity.blnGotNumPages = False Then
printEntity.blnGotNumPages = True
printEntity.strNumOfPages = Math.Ceiling(dgv.Rows.Count / RowsPerPage).ToString
sPageNo = printEntity.PageNumber.ToString + " of " + Math.Ceiling(dgv.Rows.Count / RowsPerPage).ToString
Else
sPageNo = printEntity.PageNumber.ToString + " of " + printEntity.strNumOfPages
End If

' Right Align - User Name
e.Graphics.DrawString(printEntity.UserName, dgv.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(printEntity.UserName, dgv.Font, e.MarginBounds.Width).Width), e.MarginBounds.Top + e.MarginBounds.Height + 7)
' Left Align - Date/Time
e.Graphics.DrawString(Now.ToLongDateString + " " + Now.ToShortTimeString, dgv.Font, Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top + e.MarginBounds.Height + 7)
' Center - Page No. Info
e.Graphics.DrawString(sPageNo, dgv.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, dgv.Font, e.MarginBounds.Width).Width) / 2, e.MarginBounds.Top + e.MarginBounds.Height + 31)
End Function

Private Shared Sub Validate(ByVal dgv As DataGridView, ByVal userName As String, ByVal headerText As String)
If dgv Is Nothing Then
Throw New ArgumentNullException("dgv")
End If
If String.IsNullOrEmpty(userName) = True Then
Throw New ArgumentNullException("userName")
End If
If String.IsNullOrEmpty(headerText) = True Then
Throw New ArgumentNullException("headerText")
End If
End Sub
#End Region
End Class

this is a wonderful code and it just works simply by copy & paste.

however, just a question. its seems that in this solution, there is the Print() & Preview() function. however, if let say i were to do a preview of the page BUT doesn't wan to print it out. is that possible?

sphericalx
 
 

Answer 26

When I use

PrintFactory.Print

everything works fine as described, however if you use the

PrintFactory.Preview

with the same arguments the preview dialog is perfect but if you hit the print  button you get an empty page with the date pag number and user printed but no gird.

 

Answer 27

I haven't looked at this code  for several months but I'm betting that it has something to do with a previous user's problem to which I replied... "BTW, AlexWA asked why his code would not print  out the first page of his grid and that is because he set the page to 1 in his BeginPrint Sub, so that by the time he gets to printing  out the grid contents he is already on Page 2 and since there is no data yet for Page 2, he just prints out a blank Page 2 and he's done. Not quite sure why that happens but setting the Page to 0 in the BeginPrint Sub fixes the problem. " The best thing to do is step through the code with a watch on the page setting and see what happens Good Luck!
 

Answer 28

This code  works fine and I have used it but I've found two problems: when you try to print  two dgv, printFactory creates 3 arrays (oColumnTypes, oColumnLefts, oColumnWidths) and in the method EndPrint() appends the new dgv at the oldest. I have fix this error simply writing 3 lines of code in the EndPrint method:

oColumnTypes.Clear()
oColumnLefts.Clear()
oColumnWidths.Clear()

behind the first for each construct.

The second problem is the same of previous posts: When I call printFactory.Preview() the print preview dialog starts fine but if you hit the print button, you get an empty page!!!

We have to capture the print button event??? Can sameone help us???
 

Answer 29

ONE SOLUTION...

Disable the print  button in the PreviewDialog. ;)

The code:
DirectCast(DirectCast(tempPrintDiag.Controls(1), ToolStrip).Items(0), ToolStripButton).Enabled = False

 

Answer 30

EDIT: And one more question how do I call printer setup cause print  is automated for all pages and i just want to print selected text or just first page???


Based on XANDELONGHI solution I removed button to invisible and set printer to print when you click exit on print preview

Public Shared Function Preview(ByVal dgv As DataGridView, ByVal userName As String, ByVal headerText As String, ByVal Orientation As String) As Boolean
        Validate(dgv, userName, headerText)
        Dim tempPrintFactory As PrintFactory
        tempPrintFactory = BeginPrint(dgv, userName, headerText)
        If Orientation = "L" Then
            tempPrintFactory._printDocument.DefaultPageSettings.Landscape = True
        End If
        Dim tempPrintDiag As New PrintPreviewDialog()
        DirectCast(DirectCast(tempPrintDiag.Controls(1), ToolStrip).Items(0), ToolStripButton).Visible = False
        tempPrintDiag.Document = tempPrintFactory._printDocument
        tempPrintDiag.ShowDialog()
        tempPrintFactory._printDocument.Print()
  
    End Function
If anybody knows how call print on click it would be nice

i thought something like this to declare in class don't know is it good and then call print...

        Dim tempPrintDiag As New PrintPreviewDialog()
        DirectCast(DirectCast(tempPrintDiag.Controls(1), ToolStrip).Items(0), ToolStripButton).PerformClick()
 

Answer 31

First off, I just want to say SUPER DUPER THANK YOU to the contributers!!!

I'm new to VB AND programming....  I would have been lost for days (possible weeks) working on a solution.

Now... here comes the newbee question.

Everything works fine as far as printing  goes.  But, when my print  Screen form shows up, it's very tiny... like 300 x 300.

Is it possible and where do I go to make this display with the same attributes as my other forms (i.e. - same size, background color, title bar, etc.)?

Thank you!
 

Answer 32

The first thing is the printpreview is displayed according to the actual size of your printout. If you change the size of your print  settings then you should change the preview size. the following link should give you some info on this.

http://msdn.microsoft.com/en-us/library/b1x2ca5h(VS.80).aspx


The code  on the above link shows the e.graphics method of setting up printpreview. Also the page setup determines the size.

Hope this helps

Curtis
 

Answer 33

Hello Mark, You seem like a guy who know's what you're doing.. i've got a slight problem... if you could help me that would be awesome thank you....

I'm using 3 tables, Primary, Secondary and Tertiary,
how do i get all three datagridview's to show for print  preview and print on one form?? Any idea what the code  may be as i have no idea because I have never done a print procedure for datagridview's on a form before.. but i want to show all three datagrids of the stock items that values have been changed from each datagrid on the one form...

Sorry if this doesn't make sense. if it doesn't, please get back to me and i will try and make it a bit more clearer..

Thanks in advanced

Harvey
 

Answer 34

Hey Harvey,
 Just thought I would inform you there is a working data gridview print  routine that I think will print what you want at the following post
http://social.msdn.microsoft.com/Forums/en-US/Vsexpressvb/thread/2c930600-b2ed-47d3-8fa8-4648ef43685e
 
 Will Infinity wrote the code, I just cahnge a few things to make it a little better, But it printed out with print preview and  a hard copy for me, There were some of the people had wrap around issues but in general it is a good code.

Hope this helps
curtis
 

Answer 35

Wicked! Thanks mate.. very helpful! (:
 

Answer 36

hai
i am getting an error for this code  that arraylist cannot be converted to int.so please help me to correct it
thanks in advance...
dreamflowerslove@yahoo.com
 

Answer 37

Hi kiranprabha,

 To start with you will need to provide a little more info. Your code  in the area where the error occurs and the actual error code that is displayed would be helpfull and if possible the code line the error happens on.

Curtis

 

Answer 38

Hi,

I am using your modified version of the Will_Affinity code  which works perfectly when printing  a DataGridView when I call it with either a Landscape PageSetting or a Portrait PageSetting.
What I am trying to do is to use two buttons on the DataGridView menu strip. One to call a Print in Landscape and the other to call a print  in Portrait.
If I run the program in Debug and launch the Landcape Print it previews perfectly, if I then (in the same Debug session) launch the Portrait Print the page orientation previews as Portrait but the actual Grid image is too wide and therefore tuncated at the righthand side.
If I do the opposite, start a new Debug session and launch the Portrait Print it previews perfectly, if I then (in the same Debug session) launch the Landscape Print the page orientation previews as Landscape  but the actual Grid image  is not full width. It start at the left side and seems to be about the same width as the previous Portrait image.
As you can see from the above everything works perfectly if you only do one type of print in one Debug session (ie. the first one you run is fine). It seems as if the image width for whichever print is run second somehow remains the same as the first print, even thought the PageSettings are different and must be OK or else the prints would not run OK when launched by themselves.
I've tried lots of things including defining the Landscape and Portrait versions as different PrintDocuments, but no success.
I'm not sure if this the right place to post the question, but if you have any ideas I would be most grateful or if not, could you suggest an alternative place to post the query
Thanks NewDax
 

Answer 39

 Hi NewDax,

  There may be someone else out there that is better qualified to answer this. I am not sure if I can answer you questions. But Ill try to help.

 First off I had two applications that used the print  routine one used a page setup dialog for the default printer. Set the page up for with the settings for portrait or landscape. You may have to refresh the datagridview  after changing the page setup dialog. The second used code  to change the settings.

Are you using code or a page dialog to setup the views. Though I can't see where it would make much difference. At the bottom of the link

http://social.msdn.microsoft.com/Forums/en-US/Vsexpressvb/thread/2c930600-b2ed-47d3-8fa8-4648ef43685e

the last reply has a code printer set up Did you see this?

 Have you tried to print a paper copy from the print preview screen. When priint preview comes up it has an option to print.

I willl look in to this it may take me a little while to set all of it back up and test it.

Curtis


 

Answer 40

Hi Curtis,

Thanks for your offer of help and your extemely fast response.

The PageSettings are done in code.

I tried to do the Landscape/Portrait selection in the page setup dialog but had to give up as when I changed the orientation the default margin settings flippped ie, what was my default bottom margin changed to a right hand margin. Anyway thats another problem and as I couldn't solve it I opted to use settings in code.

Thanks NewDax
 

Answer 41

  Try this code  in your code where your calling printprview.
Private Sub PrintPreview_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PrintPreview.Click
        Dim dlg As New PrintPreviewDialog()
        If PageSetupDialog1.Document.DefaultPageSettings.Landscape = False Then
            PrintDocument1.DefaultPageSettings.Landscape = False
        End If
        If PageSetupDialog1.Document.DefaultPageSettings.Landscape = True Then
            PrintDocument1.DefaultPageSettings.Landscape = True
        End If
        dlg.Document = PrintDocument1
        dlg.ShowDialog()
    End Sub
I was using a sub called from a menu. I believe the pagesetup dialog just changes the print  driver and not the document at least this caused my portrait view to print correctly when change. I use two if statements to check to see what the pagesetup is set to. You should be able to use this before call the print or printprview.

curtis

 

Answer 42

 NewDax,
 The above code  did not stop the problem for me it just change it a little. I had tried it three time and it seamed to work but I went and exited debug and restarted the app and it started having the same problem. But I still believe that the new view for some reason is not updating the datagridview  graphics.
 

Answer 43

 Have discovered some thing new that sheds light on problem. When I start debug with the pagesetup in portrait mode and I change to landscape mode the graphics image stays in portrait mode. I don't know yet how to change this. But I will keep trying.
Curtis
 

Answer 44

Hey NewDax,

 Since no one has jumped in to help I suggest starting a new question. So that others will see it. Also post your code  for the datagridview  print.
So the other people will have it to test with. I will still be looking for solution for the problem. I don't claim to know a lot about datagridview and it has a lot to it.

Curtis
 

Answer 45

Hi Curtis,

Thanks for your efforts, I'm still trying also.

I need to tidy up my code  a little before I post it, its been hacked around a lot with my different attempts.
I'm new to this game, but I will look into starting a new question.

Thanks again, NewDax
 

Answer 46

Hi Curtis,

I did try printing  from the preview and it printed with exactly the same layout as the preview ie when the preview was wrong so was the print.

I will try to raise a new question, meanwhile below is my code  module for the DataGridView Printing

Imports System.Drawing.Printing
Module PrintGrid

    ' This module Prints a DataGridView1 of multiple pages
    ' It allows user Page orientation
    ' It Previews the print  before printing
    ' It can be tailored to hide certain columns  by setting their Visible property to False
    ' in the StartPrint Sub
    ' This version has been modied so that Landscape and Portrait prints us separate PrintDocuments
    ' in an attempt to solve a problem, it if fact is no improvement over using a single PrintDocument

    Public oPortrait As Boolean

    Public WithEvents PrintDocument1 As New PrintDocument 'Added by me to overcome WithEvents required error
    Public WithEvents PrintDocument2 As New PrintDocument ' tt
    Public DataGridView1 As New DataGridView 'Added by me to overcome DataGridView1 not declared error
    ' Public DataGridView2 As New DataGridView ' tt2
    Public DefaultPageSettings As PageSettings = New PageSettings()
    Private WithEvents PrintPreviewDialog1 As New PrintPreviewDialog
    Private WithEvents PrintPreviewDialog2 As New PrintPreviewDialog 'tt
    Public WithEvents DocToPrint As New PrintDocument 'tt6
    Dim oLandscape As Boolean
    Dim GridToPrint As DataGridView
    Dim PageSetUpDialog1 As New PageSetupDialog 'trial 1
    Dim PageSetUpDialog2 As New PageSetupDialog ' tt

    Private lPageNo As String = ""

    Private sPageNo As String = ""

    Private oStringFormat As StringFormat

    Private oStringFormatComboBox As StringFormat

    Private oButton As Button

    Private oCheckbox As CheckBox

    Private oComboBox As ComboBox

    Private nTotalWidth As Int16

    Private nRowPos As Int16

    Private NewPage As Boolean

    Private nPageNo As Int16

    Private Header As String

    Private sUserName As String = ""
   
    Public Sub StartPrintL(ByVal GridToPrint) 'ByVal GridToPrint As DataGridView)

        DataGridView1 = GridToPrint
        DocToPrint = PrintDocument1

        'oLandscape = True 'used in previous attempt

        ' Set up Default Page Settings
        PrintDocument1.DefaultPageSettings.Landscape = True
        PrintDocument1.DefaultPageSettings.Margins.Left = 10
        PrintDocument1.DefaultPageSettings.Margins.Right = 10
        PrintDocument1.DefaultPageSettings.Margins.Top = 25
        PrintDocument1.DefaultPageSettings.Margins.Bottom = 50

        ' DataGridView1.Columns(2).Visible = False ' Use to hide a col. (index no.)at runtime

        PrintDocument1.OriginAtMargins = True ' takes margins into account 

        'PageSetUpDialog1.PageSettings = DefaultPageSettings ' Displays page setting dialog-removed due to problems
        ' PageSetUpDialog1.ShowDialog()                        ' with margins when paper orientation changed

        Dim PrintPreviewDialog1 As New PrintPreviewDialog()

        ' PrintDocument1.DefaultPageSettings = PageSetUpDialog1.PageSettings ' Sets page settings to those from PageSetupDialog
        PrintPreviewDialog1.ClientSize = New System.Drawing.Size(600, 600) ' Set Dialog box initial size
        PrintPreviewDialog1.Document = PrintDocument1 ' Previews print
        PrintPreviewDialog1.ShowDialog()


        'PrintDocument1.Print() ' Alternative for direct print
    End Sub
    Public Sub StartPrintP(ByVal GridToPrint)

        DocToPrint = PrintDocument2
        DataGridView1 = GridToPrint

        ' DataGridView1.Columns(2).Visible = False ' Use to hide a col. (index no.)

        PrintDocument2.OriginAtMargins = True ' takes margins into account 
        ' Set up Default Page Settings
        PrintDocument2.DefaultPageSettings.Landscape = False
        PrintDocument2.DefaultPageSettings.Margins.Left = 10
        PrintDocument2.DefaultPageSettings.Margins.Right = 10
        PrintDocument2.DefaultPageSettings.Margins.Top = 25
        PrintDocument2.DefaultPageSettings.Margins.Bottom = 50

        Dim PrintPreviewDialog2 As New PrintPreviewDialog()

        'PrintDocument1.DefaultPageSettings = PageSetUpDialog2.PageSettings ' Sets page settings to those from PageSetupDialog
        PrintPreviewDialog2.ClientSize = New System.Drawing.Size(600, 600) 'tt Set Dialog box initial size
        PrintPreviewDialog2.Document = PrintDocument2 ' Previews print
        PrintPreviewDialog2.ShowDialog()


        'PrintDocument1.Print()' Alternative for direct print
    End Sub

    ' 'Public Sub PrintDocument1_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.BeginPrint
    ' Test using DocToPrint to carry in a different PrintDocument for Landscape and Portrait
    ' Same problem as using single PrintDocument

    Public Sub DocToPrint_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles DocToPrint.BeginPrint

        oStringFormat = New StringFormat

        oStringFormat.Alignment = StringAlignment.Near

        oStringFormat.LineAlignment = StringAlignment.Center

        oStringFormat.Trimming = StringTrimming.EllipsisCharacter

        oStringFormatComboBox = New StringFormat

        oStringFormatComboBox.LineAlignment = StringAlignment.Center

        oStringFormatComboBox.FormatFlags = StringFormatFlags.NoWrap

        oStringFormatComboBox.Trimming = StringTrimming.EllipsisCharacter

        oButton = New Button

        oCheckbox = New CheckBox

        oComboBox = New ComboBox

        nTotalWidth = 0

        For Each oColumn As DataGridViewColumn In DataGridView1.Columns
            If oColumn.Visible = True Then ' Prints only Visible columns
                nTotalWidth += oColumn.Width
            End If
        Next

        nPageNo = 1

        NewPage = True

        nRowPos = 0

    End Sub
    Public Sub DocToPrint_EndPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.EndPrint
        'Not currently used
    End Sub

    '' Public Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
    ' Test using DocToPrint to carry in a different PrintDocument for Landscape and Portrait
    ' Same problem as using single PrintDocument
    Public Sub DocToPrint_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles DocToPrint.PrintPage
        Using the_pen As New Pen(Color.Black, 5) ' For debugging only
            e.Graphics.DrawRectangle(the_pen, e.MarginBounds)
        End Using

        Header = "Books DataGridView"

        Static oColumnLefts As New ArrayList

        Static oColumnWidths As New ArrayList

        Static oColumnTypes As New ArrayList

        Static nHeight As Int16

        Dim nWidth, i, nRowsPerPage As Int16

        Dim nTop As Int16 = e.MarginBounds.Top

        Dim nLeft As Int16 = e.MarginBounds.Left

        If nPageNo = 1 Then

            For Each oColumn As DataGridViewColumn In DataGridView1.Columns
                If oColumn.Visible = True Then ' Prints cols with Visible property
                    nWidth = CType(Math.Floor(oColumn.Width / nTotalWidth * nTotalWidth * (e.MarginBounds.Width / nTotalWidth)), Int16)

                    nHeight = e.Graphics.MeasureString(oColumn.HeaderText, oColumn.InheritedStyle.Font, nWidth).Height + 11

                    oColumnLefts.Add(nLeft)

                    oColumnWidths.Add(nWidth)

                    oColumnTypes.Add(oColumn.GetType)

                    nLeft += nWidth
                End If

            Next

        End If

        Do While nRowPos < DataGridView1.Rows.Count - 1 ' Reports of failing to Print last 
            'row. If so remove -1 from above line
            Dim oRow As DataGridViewRow = DataGridView1.Rows(nRowPos)

            If nTop + nHeight >= e.MarginBounds.Height + e.MarginBounds.Top Then

                DrawFooter(e, nRowsPerPage)

                NewPage = True

                nPageNo += 1

                e.HasMorePages = True

                Exit Sub

            Else

                If NewPage Then

                    ' Draw Header

                    e.Graphics.DrawString(Header, New Font(DataGridView1.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top - e.Graphics.MeasureString(Header, New Font(DataGridView1.Font, FontStyle.Bold), e.MarginBounds.Width).Height - 13)

                    ' Draw Columns

                    nTop = e.MarginBounds.Top

                    i = 0

                    For Each oColumn As DataGridViewColumn In DataGridView1.Columns
                        If oColumn.Visible = True Then ' Prints cols with Visible property
                            e.Graphics.FillRectangle(New SolidBrush(Drawing.Color.LightGray), New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))

                            e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))

                            e.Graphics.DrawString(oColumn.HeaderText, oColumn.InheritedStyle.Font, New SolidBrush(oColumn.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)

                            i += 1
                        End If
                    Next

                    NewPage = False

                End If

                nTop += nHeight

                i = 0

                Dim svalue As String

                For Each oCell As DataGridViewCell In oRow.Cells
                    If oCell.Visible = True Then ' Prints cols with Visible property
                        If oCell.Value IsNot Nothing Then

                            svalue = oCell.Value.ToString

                        Else

                            svalue = ""

                        End If

                        If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then

                            e.Graphics.DrawString(svalue, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)

                        ElseIf oColumnTypes(i) Is GetType(DataGridViewButtonColumn) Then

                            oButton.Text = oCell.Value.ToString

                            oButton.Size = New Size(oColumnWidths(i), nHeight)

                            Dim oBitmap As New Bitmap(oButton.Width, oButton.Height)

                            oButton.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, _
                            oBitmap.Height))

                            e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))

                        ElseIf oColumnTypes(i) Is GetType(DataGridViewCheckBoxColumn) Then

                            oCheckbox.Size = New Size(14, 14)

                            oCheckbox.Checked = CType(oCell.Value, Boolean)

                            Dim oBitmap As New Bitmap(oColumnWidths(i), nHeight)

                            Dim oTempGraphics As Graphics = Graphics.FromImage(oBitmap)

                            oTempGraphics.FillRectangle(Brushes.White, New Rectangle(0, _
                            0, oBitmap.Width, oBitmap.Height))

                            oCheckbox.DrawToBitmap(oBitmap, New Rectangle(CType((oBitmap.Width - oCheckbox.Width) / 2, Int32), CType((oBitmap.Height - oCheckbox.Height) / 2, Int32), oCheckbox.Width, _
                            oCheckbox.Height))

                            e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))

                        ElseIf oColumnTypes(i) Is GetType(DataGridViewComboBoxColumn) Then

                            oComboBox.Size = New Size(oColumnWidths(i), nHeight)

                            Dim oBitmap As New Bitmap(oComboBox.Width, oComboBox.Height)

                            oComboBox.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, _
                            oBitmap.Height))

                            e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))

                            e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, _
                            New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i) + 1, nTop, oColumnWidths(i) _
                            - 16, nHeight), oStringFormatComboBox)

                        ElseIf oColumnTypes(i) Is GetType(DataGridViewImageColumn) Then

                            Dim oCellSize As Rectangle = New Rectangle(oColumnLefts(i), nTop, _
                            oColumnWidths(i), nHeight)

                            Dim oImageSize As Size = CType(oCell.Value, Image).Size

                            e.Graphics.DrawImage(oCell.Value, New Rectangle(oColumnLefts(i) + CType(((oCellSize.Width - oImageSize.Width) / 2), Int32), nTop + CType(((oCellSize.Height - oImageSize.Height) / 2), Int32), _
                            CType(oCell.Value, Image).Width, CType(oCell.Value,  _
                            Image).Height))

                        End If

                        e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), _
                        nTop, oColumnWidths(i), nHeight))

                        i += 1
                    End If
                Next

            End If

            nRowPos += 1

            nRowsPerPage += 1

        Loop

        DrawFooter(e, nRowsPerPage)

        e.HasMorePages = False

    End Sub

    Public Sub DrawFooter(ByVal e As System.Drawing.Printing.PrintPageEventArgs, _
    ByVal RowsPerPage As Int32)

        Dim sPageNo As String = nPageNo.ToString + " of "

        If nPageNo = "1" Then

            lPageNo = Math.Ceiling((DataGridView1.Rows.Count - 1) / RowsPerPage).ToString()
            sPageNo = nPageNo.ToString + " of " + lPageNo

        Else

            sPageNo = nPageNo.ToString + " of " + lPageNo

        End If

        ' Right Align - User Name

        e.Graphics.DrawString(sUserName, DataGridView1.Font, Brushes.Black, _
        e.MarginBounds.Left + (e.MarginBounds.Width - _
        e.Graphics.MeasureString(sPageNo, DataGridView1.Font, _
        e.MarginBounds.Width).Width), e.MarginBounds.Top + _
        e.MarginBounds.Height + 7)

        ' Left Align - Date/Time

        e.Graphics.DrawString(Now.ToLongDateString + " " + Now.ToShortTimeString, _
        DataGridView1.Font, Brushes.Black, e.MarginBounds.Left, _
        e.MarginBounds.Top + e.MarginBounds.Height + 7) '7 is a mod (was 31)to raise page no. up one line

        ' Center - Page No. Info

        e.Graphics.DrawString(sPageNo, DataGridView1.Font, _
        Brushes.Black, e.MarginBounds.Left + _
        (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, _
        DataGridView1.Font, e.MarginBounds.Width).Width) / 2, _
        e.MarginBounds.Top + e.MarginBounds.Height + 7)

    End Sub
End Module
The calling code calls a specific version of the Sub StartPrint depending upon the click event of either the Landscape or Portrait print buttons . Code below :

 Private Sub ToolStripButton1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolStripButton1.Click
        ' OPortrait = False ' not used in this version
        PrintGrid.StartPrintL(DataGridView1) 'CallPrint module Sub
    End Sub

    Private Sub ToolStripButton2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPortrait.Click
        ' OPortrait = True 'not used in this version
        PrintGrid.StartPrintP(DataGridView1) 'CallPrint module Sub for portrait
    End Sub
 

Answer 47

For those who are reading this post there has been found a fix for this problem. it is as follows.
 Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
       
        Static oColumnLefts As New ArrayList
        Static oColumnWidths As New ArrayList
        Static oColumnTypes As New ArrayList
        Static nHeight As Int16

        Dim nWidth, i, nRowsPerPage As Int16
        Dim nTop As Int16 = e.MarginBounds.Top
        Dim nLeft As Int16 = e.MarginBounds.Left


' add the 3 .clear statements below

        oColumnLefts.Clear()
        oColumnWidths.Clear()
        oColumnTypes.Clear()


        If nPageNo = 1 Then
            For Each oColumn As DataGridViewColumn In DataGridView1.Columns
                nWidth = CType(
The problem was the Ocolumns are static and were being added to causing the grid to to be off the screen.

Curtis
 

Answer 48

Discover a Mistake I made in the logic of the above code.

 It should be
 Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
       
        Static oColumnLefts As New ArrayList
        Static oColumnWidths As New ArrayList
        Static oColumnTypes As New ArrayList
        Static nHeight As Int16

        Dim nWidth, i, nRowsPerPage As Int16
        Dim nTop As Int16 = e.MarginBounds.Top
        Dim nLeft As Int16 = e.MarginBounds.Left
If nPageNo = 1 Then

' add the 3 .clear statements below

        oColumnLefts.Clear()
        oColumnWidths.Clear()
        oColumnTypes.Clear()


        
            For Each oColumn As DataGridViewColumn In DataGridView1.Columns
                nWidth = CType(
 

Answer 49

Hello Curtis or anyone who can help me. This code  does seem elegant, but I do get an error when I run it. At the following location:

For Each oCell As DataGridViewCell In oRow.Cells
                    If oCell.Visible = True Then
                        If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then
                            e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), printEntity.StringFormat)

I get this error.

System.NullReferenceException was unhandled
  Message="Object reference not set to an instance of an object."
  Source="AssemblyTreeManual3"
  StackTrace:


Am I lacking a reference or setting change? Thanks for the help.

Hollertrek     

 

Answer 50

Hollertrek51,

 I edited this post to imform you the code  you posted is by Yaboro and not the code I used, below is the code I used. Also the modifications I made is for the code that I am using and may not work for Yaboro's code.

 A null reference means one of the values in the object has nothing in it. Witch Line exactly has the error? You have 4 lines and each one has from 1 to 8 objects that could return the null reference error. When It errors you shoud be able to put the cursor over the different objects and see the value they hold it should show witch one is null. Sometimes it doesn,t work if the reference is from a different function or class.

 Then after you have found the object or variable that is null you have to backtrack to where it is getting its value and find  out why it is null.

The code works for me and without seeing the error and finding out witch object has the null in it, I could not tell you. If it was a setting or reference missing it would be a different error and would have errored out sooner.

The above code iterates through each cell in a row and if the cell is visible then it checks to see ocolumn type which is a stored variable is the same as the type DataGridview TextBox column type or link column type. If this s true then it draws the cell to the graphics page in memory.
 

 Also did you make the change in code that is shown in my last post? This modfication I made has not been fully tested for all different size of collums or cells and this does effect the For Each Ocell.

 You might post the number of columns  and approximately their widiths. so I can try to duplicate this error.

Curtis


Always Lost in Code, Always mark answers as correct if they answer you question and solve your problem. This way others when searching for similar problems can find the answer faster.
 

Answer 51

Here is the modified version with a printprview and print  dialogs setup. I removed the variables that I used for my application but here is the imports and variables. Aslo shown is the print routine with the page and print dialogs. Of course they are being called from a menustrip.

   Imports System
Imports System.IO
Imports System.IO.Ports
Imports System.Text
Imports Microsoft.VisualBasic
Imports System.Drawing
Imports System.Drawing.Printing
Imports System.Windows.Forms
Public Class Spreadsheet
    
    
    Public columCount As Int64
    Public HeaderS As String
    Public rows(1000, 8) As String
    Public row As String
    Private lPageNo As String = ""
    Private sPageNo As String = ""
    Private oStringFormat As StringFormat
    Private oStringFormatComboBox As StringFormat
    Private oButton As Button
    Private oCheckbox As CheckBox
    Private oComboBox As ComboBox
    Private nTotalWidth As Int16
    Private nRowPos As Int16
    Private NewPage As Boolean
    Private nPageNo As Int16
    Private Header As String
 
 Private Sub PrintDocument_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PrintDocument.Click


        PrintDialog1.AllowSomePages = True
        ' Show the help button.
        PrintDialog1.ShowHelp = True
        PrintDialog1.Document = PrintDocument1

        Dim result As DialogResult = PrintDialog1.ShowDialog()
        ' If the result is OK then print the document.
        If (result = DialogResult.OK) Then
            PrintDocument1.Print()
        End If
    End Sub
    Private Sub PrintPreview_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PrintPreview.Click
       

        Dim dlg As New PrintPreviewDialog()
        Dim d

        dlg.Document = printdocument1
        d = printdocument1.DefaultPageSettings.Bounds


        dlg.ShowDialog()
    End Sub
    Private Sub PageSetup_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PageSetup.Click

        ' Sets the print document's color setting to false,
        ' so that the page will not be printed in color.
        'PageSetupDialog1.Document.DefaultPageSettings.Color = False
        'PageSetupDialog1.ShowDialog()

        PageSetupDialog1.Document = PrintDocument1
        PageSetupDialog1.AllowOrientation = True
        PageSetupDialog1.AllowPrinter = True
        'Show the dialog storing the result.
        Dim result As DialogResult = PageSetupDialog1.ShowDialog




    End Sub


      Private Sub InitializeDataGridView()
        ' Create an unbound DataGridView by declaring a column count.
        DataGridView1.ColumnCount = columCount
        DataGridView1.ColumnHeadersVisible = True
        DataGridView1.RowHeadersVisible = True
        ' Set the column header style.
        Dim columnHeaderStyle As New DataGridViewCellStyle()
        columnHeaderStyle.BackColor = Color.White
        columnHeaderStyle.Font = New Font("Verdana", 10, FontStyle.Bold)
        DataGridView1.ColumnHeadersDefaultCellStyle = columnHeaderStyle
    End Sub

     Private Sub PrintDocument1_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.BeginPrint

        oStringFormat = New StringFormat
        oStringFormat.Alignment = StringAlignment.Near
        oStringFormat.LineAlignment = StringAlignment.Center
        oStringFormat.Trimming = StringTrimming.EllipsisCharacter

        oStringFormatComboBox = New StringFormat
        oStringFormatComboBox.LineAlignment = StringAlignment.Center
        oStringFormatComboBox.FormatFlags = StringFormatFlags.NoWrap
        oStringFormatComboBox.Trimming = StringTrimming.EllipsisCharacter

        oButton = New Button
        oCheckbox = New CheckBox
        oComboBox = New ComboBox

        nTotalWidth = 0
        For Each oColumn As DataGridViewColumn In DataGridView1.Columns

            nTotalWidth += oColumn.Width

        Next
        nPageNo = 1
        NewPage = True
        nRowPos = 0



    End Sub
    Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
       
        Static oColumnLefts As New ArrayList
        Static oColumnWidths As New ArrayList
        Static oColumnTypes As New ArrayList
        Static nHeight As Int16

        Dim nWidth, i, nRowsPerPage As Int16
        Dim nTop As Int16 = e.MarginBounds.Top
        Dim nLeft As Int16 = e.MarginBounds.Left

        If nPageNo = 1 Then
            oColumnLefts.Clear()
            oColumnWidths.Clear()
            oColumnTypes.Clear()
            For Each oColumn As DataGridViewColumn In DataGridView1.Columns
                nWidth = CType(Math.Floor(oColumn.Width / nTotalWidth * nTotalWidth * (e.MarginBounds.Width / nTotalWidth)), Int16)
                nHeight = e.Graphics.MeasureString(oColumn.HeaderText, oColumn.InheritedStyle.Font, nWidth).Height + 11
                oColumnLefts.Add(nLeft)
                oColumnWidths.Add(nWidth)
                oColumnTypes.Add(oColumn.GetType)
                nLeft += nWidth
            Next
        End If
        Do While nRowPos < DataGridView1.Rows.Count - 1
            Dim oRow As DataGridViewRow = DataGridView1.Rows(nRowPos)
            If nTop + nHeight >= e.MarginBounds.Height + e.MarginBounds.Top Then
                DrawFooter(e, nRowsPerPage)
                NewPage = True
                nPageNo += 1
                e.HasMorePages = True
                Exit Sub
            Else
                If NewPage Then
                    ' Draw Header
                    e.Graphics.DrawString(Header, New Font(DataGridView1.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top - e.Graphics.MeasureString(Header, New Font(DataGridView1.Font, FontStyle.Bold), e.MarginBounds.Width).Height - 13)
                    ' Draw Columns
                    nTop = e.MarginBounds.Top
                    i = 0
                    For Each oColumn As DataGridViewColumn In DataGridView1.Columns
                        e.Graphics.FillRectangle(New SolidBrush(Drawing.Color.LightGray), New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
                        e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
                        e.Graphics.DrawString(oColumn.HeaderText, oColumn.InheritedStyle.Font, New SolidBrush(oColumn.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)
                        i += 1
                    Next
                    NewPage = False
                End If
                nTop += nHeight
                i = 0
                Dim svalue As String
                For Each oCell As DataGridViewCell In oRow.Cells
                    If oCell.Value <> Nothing Then
                        svalue = oCell.Value.ToString
                    Else
                        svalue = ""
                    End If
                    If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then
                        e.Graphics.DrawString(svalue, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)
                    ElseIf oColumnTypes(i) Is GetType(DataGridViewButtonColumn) Then
                        oButton.Text = oCell.Value.ToString
                        oButton.Size = New Size(oColumnWidths(i), nHeight)
                        Dim oBitmap As New Bitmap(oButton.Width, oButton.Height)
                        oButton.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, _
                                                                    oBitmap.Height))
                        e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
                    ElseIf oColumnTypes(i) Is GetType(DataGridViewCheckBoxColumn) Then
                        oCheckbox.Size = New Size(14, 14)
                        oCheckbox.Checked = CType(oCell.Value, Boolean)
                        Dim oBitmap As New Bitmap(oColumnWidths(i), nHeight)
                        Dim oTempGraphics As Graphics = Graphics.FromImage(oBitmap)
                        oTempGraphics.FillRectangle(Brushes.White, New Rectangle(0, _
                                                    0, oBitmap.Width, oBitmap.Height))
                        oCheckbox.DrawToBitmap(oBitmap, New Rectangle(CType((oBitmap.Width _
                                  - oCheckbox.Width) / 2, Int32), CType((oBitmap.Height _
                                  - oCheckbox.Height) / 2, Int32), oCheckbox.Width, _
                                  oCheckbox.Height))
                        e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
                    ElseIf oColumnTypes(i) Is GetType(DataGridViewComboBoxColumn) Then
                        oComboBox.Size = New Size(oColumnWidths(i), nHeight)
                        Dim oBitmap As New Bitmap(oComboBox.Width, oComboBox.Height)
                        oComboBox.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, _
                                                                      oBitmap.Height))
                        e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
                        e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, _
                                   New SolidBrush(oCell.InheritedStyle.ForeColor), New  _
                                   RectangleF(oColumnLefts(i) + 1, nTop, oColumnWidths(i) _
                                   - 16, nHeight), oStringFormatComboBox)
                    ElseIf oColumnTypes(i) Is GetType(DataGridViewImageColumn) Then
                        Dim oCellSize As Rectangle = New Rectangle(oColumnLefts(i), nTop, _
                                                                   oColumnWidths(i), nHeight)
                        Dim oImageSize As Size = CType(oCell.Value, Image).Size
                        e.Graphics.DrawImage(oCell.Value, New Rectangle(oColumnLefts(i) _
                                   + CType(((oCellSize.Width _
                                   - oImageSize.Width) / 2), Int32), nTop + CType _
                                   (((oCellSize.Height - oImageSize.Height) / 2), Int32), _
                                   CType(oCell.Value, Image).Width, CType(oCell.Value,  _
                                   Image).Height))
                    End If
                    e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), _
                                                         nTop, oColumnWidths(i), nHeight))
                    i += 1
                Next
            End If
            nRowPos += 1
            nRowsPerPage += 1
        Loop
        DrawFooter(e, nRowsPerPage)
        e.HasMorePages = False
    End Sub

    Private Sub DrawFooter(ByVal e As System.Drawing.Printing.PrintPageEventArgs, _
                           ByVal RowsPerPage As Int32)

        Dim sPageNo As String = nPageNo.ToString + " of "
        If nPageNo = "1" Then
            ' rowsC = Math.Ceiling(DataGridView1.Rows.Count - 1)
            lPageNo = Math.Ceiling((DataGridView1.Rows.Count - 1) / RowsPerPage).ToString()
            sPageNo = nPageNo.ToString + " of " + lPageNo
        Else
            sPageNo = nPageNo.ToString + " of " + lPageNo
        End If

        ' Right Align - User Name
        e.Graphics.DrawString(sUserName, DataGridView1.Font, Brushes.Black, _
                              e.MarginBounds.Left + (e.MarginBounds.Width - _
                              e.Graphics.MeasureString(sPageNo, DataGridView1.Font, _
                              e.MarginBounds.Width).Width), e.MarginBounds.Top + _
                              e.MarginBounds.Height + 7)
        ' Left Align - Date/Time
        e.Graphics.DrawString(Now.ToLongDateString + " " + Now.ToShortTimeString, _
                              DataGridView1.Font, Brushes.Black, e.MarginBounds.Left, _
                              e.MarginBounds.Top + e.MarginBounds.Height + 7)
        ' Center  - Page No. Info
        e.Graphics.DrawString(sPageNo, DataGridView1.Font, _
                              Brushes.Black, e.MarginBounds.Left + _
                              (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, _
                               DataGridView1.Font, e.MarginBounds.Width).Width) / 2, _
                               e.MarginBounds.Top + e.MarginBounds.Height + 31)
    End Sub

End Class
 

Answer 52

Hello Curtis or anyone who can help me. This code  does seem elegant, but I do get an error when I run it. At the following location:

For Each oCell As DataGridViewCell In oRow.Cells
                    If oCell.Visible = True Then
                        If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then
                            e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), printEntity.StringFormat)

I get this error.

System.NullReferenceException was unhandled
  Message="Object reference not set to an instance of an object."
  Source="AssemblyTreeManual3"
  StackTrace:


Am I lacking a reference or setting change? Thanks for the help.

Hollertrek     


I just figured out that the code you posted is Yarboro's posted code. I don't have his code in a working Application. I posted the code I have in A working application above. It was originally written by Will Infinity. If you are using PrintDocument to call the print  routine this will work but if your calling in a different way I don't Know if this code woud work or not.

There is two or three different codes posted above.

Curtis

 


Always Lost in Code, Always mark answers as correct if they answer you question and solve your problem. This way others when searching for similar problems can find  the answer faster.
 

Answer 53

Hi Curtis,

Thanks for the response. I'm trying a couple things here. First, my example code  was to give a context, the last line producing the error. It appears the oCell.Value.ToString is the null value. If that line is taken out I'm able to print  the grid with no values. For some reason the values are not getting to the grid. I'll have to look at that more carefully.

 

Secondly, I've placed your code and as a class it doesn't recognize the controls on the form. If I remove the class heading the controls are then recognized but I now get the error at each sub heading, statement not valid in a namespace . I must be missing something simple.

 

Jon

 

Answer 54

Gilberto74Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
 
Vote As Helpful
I have a workaround to your problem.
There's a better solution i guess, but anyway...

01. FIRST: Identify the position of your datagridview  column with datetime format, starting at ZERO for the first column;
02. SECOND: Change this portion of code:

(...)
If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then
e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(CSng(oColumnLefts(i)), nTop, CSng(oColumnWidths(i)), nHeight), oStringFormat)
ElseIf oColumnTypes(i) Is GetType(DataGridViewButtonColumn) Then
(...)

TO THIS:
(...)
If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then
if i=<>2 (supose that's the position number of your datetime format column) then
e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(CSng(oColumnLefts(i)), nTop, CSng(oColumnWidths(i)), nHeight), oStringFormat)
else
e.Graphics.DrawString(iif(oCell.Value.ToString="",oCell.Value.ToString,oCell.Value), oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(CSng(oColumnLefts(i)), nTop, CSng(oColumnWidths(i)), nHeight), oStringFormat)
end if
ElseIf oColumnTypes(i) Is GetType(DataGridViewButtonColumn) Then
(...)

It works for me!
 

Answer 55

You can download a Visual Studio 2010 solution at:

http://www.planetsourcecode.com/vb/scripts/ShowCode.asp?txtCodeId=7777&lngWId=10

It contains the solutions that have been posted in this forum, as well as a few other features.
 
 

Answer 57

I used this code  and works perfect as i need for direct print.

Thanks a lot.

 

Answer 58

There isn't any built in printing  support, so there are two options:
1) Use the standard printing system provided by Windows Forms and manually print  out the information that you want. Check out the documentation for PrintPage and PrintDocument

2) Use the DataGridView's clipboard copy support to copy the content to an Excel file and then print that.

Hope this helps,
-mark
DataGridView Program Manager
Microsoft
This post is provided "as-is"
 

Answer 59

ok, I just wrote a class that works with PrintPage and PrintDocument and everything looks good in the print  preview dialog. However, as soon as I'm printing, only the grid headers and some extra text I added (page numbers, etc.) are printed. None of the DataGridView content that I painted and is visible in the print preview is printed to the output document.

Any idea why this could be the case?
 

Answer 60

Wow, I haven't see that, unless you are using TextRenderer.DrawText for your printing. Unfortunitely TextRenderer.DrawText uses GDI while Graphics.DrawString uses GDI+. GDI drawing with our current print  engine doesn't work correctly, so you'll need to use Graphics.DrawString.

Let me know if that works. If that isn't the case then can you file a bug and we'll investigate it? Thanks

-mark
DataGridView Program Manager
Microsoft
This post is provided "as-is"
 

Answer 61

I'm using DrawString...

here's my code  ... it's a bit messy right now but should do the job ;)


privatevoid printDocument_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
        {
            int x = 0;
            int y = 100;
            int rowGap = 20;
            int colGap = 5;
            int leftMargin = 50;
 
            int linesPerPage = e.MarginBounds.Height / _dataGridView.DefaultCellStyle.Font.Height;
            Font font = new Font(_dataGridView.DefaultCellStyle.Font.FontFamily, _dataGridView.DefaultCellStyle.Font.Size);
            Font headingFont = new Font("Arial", 10, FontStyle.Bold);
            Font captionFont = new Font("Arial", 10, FontStyle.Bold);
            Brush brush = new SolidBrush(Color.Black);
            string cellValue = "";

            e.Graphics.DrawString("Erstellt von " + ObjectStore.Account.UserName + " am " + DateTime.Now.ToLongDateString(), captionFont, brush, new PointF(50, 50));
            e.Graphics.DrawString("Seite " + _pageNumber, captionFont, brush, new PointF(e.PageBounds.Width - 100, e.PageBounds.Height - 50));

            int rowCount = _dataGridView.Rows.Count;
            int colCount = _dataGridView.Columns.Count;

            y += rowGap;
            x = leftMargin;
            foreach (DataGridViewColumn column in _dataGridView.Columns)
            {
                if(column.GetType() != typeof(DataGridViewButtonColumn) && column.GetType() != typeof(DataGridViewCheckBoxColumn))
                {
                    cellValue = column.HeaderText;
                    e.Graphics.DrawString(cellValue, headingFont, brush, x, y);
                    x += column.Width + colGap;
                }
            }

            int count = 0;
            for (int i = _rowPosition; i < _dataGridView.Rows.Count; i++)
            {
                y += rowGap;
                x = leftMargin;

                foreach (DataGridViewColumn column in _dataGridView.Columns)
                {
                    if (column.GetType() != typeof(DataGridViewButtonColumn) && column.GetType() != typeof(DataGridViewCheckBoxColumn))
                    {
                        cellValue = _dataGridView.Rows//emoticons/emotion-55.gif" alt="Idea" />.Cells[column.Index].Value.ToString();
                        e.Graphics.DrawString(cellValue, captionFont, brush, x, y);
                        x += column.Width + colGap;
                        y = y + rowGap * (cellValue.Split(new char[] { '\r', '\n' }).Length - 1);
                    }
                }

                _rowPosition++;
                count++;

                if (count > linesPerPage)
                {
                    break;
                }
            }

            if (_rowPosition > linesPerPage && _rowPosition < _dataGridView.Rows.Count)
            {
                _pageNumber++;
                e.HasMorePages = true;
            }
        }

 

 

Answer 62

any takers? ;)
 

Answer 63

The MSDN library provides the following guidance for printing  a DataGrid...

This example demonstrates printing a DataGrid control.

Example
private void printGrid_Click(System.Object sender, System.EventArgs e) { printDocument1.Print(); } private void printDocument1_PrintPage(System.Object sender, System.Drawing.Printing.PrintPageEventArgs e) { PaintEventArgs myPaintArgs = new PaintEventArgs(e.Graphics, new Rectangle(new Point(0, 0), this.Size)); this.InvokePaint(dataGrid1, myPaintArgs);







Is it planned to have this work for the DataGridView?
I have tried to use it but it printed only the Grid, omitting the contents of the cells.
Does the code  in the above example work in VS 2005? That is, maybe I should copy
the contents of my DataGridView to a DataGrid and print  from there!
 

Answer 64

For anyone needing to know how to start printing  a grid, here is some code  I whipped up after not finding any samples I could heist from someone else.  I'm sure there are better ways to do this, but like I said, this is a start.  Probably why MS doesn't offer a print  function or component is because there is truly an unlimited number of configurations for a print setup.  To achieve most of them isn't even rocket science, the beauty of VB.NET.  Cheers.     Private oStringFormat As StringFormat    Private oStringFormatComboBox As StringFormat    Private oButton As Button    Private oCheckbox As CheckBox    Private oComboBox As ComboBox     Private nTotalWidth As Int16    Private nRowPos As Int16    Private NewPage As Boolean    Private nPageNo As Int16    Private Header As String = "Header Test"    Private sUserName As String = "Will"     Private Sub PrintDocument1_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.BeginPrint         oStringFormat = New StringFormat        oStringFormat.Alignment = StringAlignment.Near        oStringFormat.LineAlignment = StringAlignment.Center        oStringFormat.Trimming = StringTrimming.EllipsisCharacter         oStringFormatComboBox = New StringFormat        oStringFormatComboBox.LineAlignment = StringAlignment.Center        oStringFormatComboBox.FormatFlags = StringFormatFlags.NoWrap        oStringFormatComboBox.Trimming = StringTrimming.EllipsisCharacter         oButton = New Button        oCheckbox = New CheckBox        oComboBox = New ComboBox         nTotalWidth = 0        For Each oColumn As DataGridViewColumn In DataGridView1.Columns             nTotalWidth += oColumn.Width         Next        nPageNo = 1        NewPage = True        nRowPos = 0     End Sub     Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage             Static oColumnLefts As New ArrayList            Static oColumnWidths As New ArrayList            Static oColumnTypes As New ArrayList            Static nHeight As Int16             Dim nWidth, i, nRowsPerPage As Int16            Dim nTop As Int16 = e.MarginBounds.Top            Dim nLeft As Int16 = e.MarginBounds.Left             If nPageNo = 1 Then                 For Each oColumn As DataGridViewColumn In DataGridView1.Columns                     nWidth = CType(Math.Floor(oColumn.Width / nTotalWidth * nTotalWidth * (e.MarginBounds.Width / nTotalWidth)), Int16)                     nHeight = e.Graphics.MeasureString(oColumn.HeaderText, oColumn.InheritedStyle.Font, nWidth).Height + 11                     oColumnLefts.Add(nLeft)                    oColumnWidths.Add(nWidth)                    oColumnTypes.add(oColumn.GetType)                    nLeft += nWidth                 Next             End If             Do While nRowPos < DataGridView1.Rows.Count - 1                 Dim oRow As DataGridViewRow = DataGridView1.Rows(nRowPos)                 If nTop + nHeight >= e.MarginBounds.Height + e.MarginBounds.Top Then                     DrawFooter(e, nRowsPerPage)                     NewPage = True                    nPageNo += 1                    e.HasMorePages = True                    Exit Sub                 Else                     If NewPage Then                         ' Draw Header                        e.Graphics.DrawString(Header, New Font(DataGridView1.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top - e.Graphics.MeasureString(Header, New Font(DataGridView1.Font, FontStyle.Bold), e.MarginBounds.Width).Height - 13)                         ' Draw Columns                        nTop = e.MarginBounds.Top                        i = 0                        For Each oColumn As DataGridViewColumn In DataGridView1.Columns                             e.Graphics.FillRectangle(New SolidBrush(Drawing.Color.LightGray), New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))                            e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))                            e.Graphics.DrawString(oColumn.HeaderText, oColumn.InheritedStyle.Font, New SolidBrush(oColumn.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)                            i += 1                         Next                        NewPage = False                     End If                     nTop += nHeight                    i = 0                    For Each oCell As DataGridViewCell In oRow.Cells                         If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then                             e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)                         ElseIf oColumnTypes(i) Is GetType(DataGridViewButtonColumn) Then                             oButton.Text = oCell.Value.ToString                            oButton.Size = New Size(oColumnWidths(i), nHeight)                            Dim oBitmap As New Bitmap(oButton.Width, oButton.Height)                            oButton.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))                            e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))                         ElseIf oColumnTypes(i) Is GetType(DataGridViewCheckBoxColumn) Then                             oCheckbox.Size = New Size(14, 14)                            oCheckbox.Checked = CType(oCell.Value, Boolean)                            Dim oBitmap As New Bitmap(oColumnWidths(i), nHeight)                            Dim oTempGraphics As Graphics = Graphics.FromImage(oBitmap)                            oTempGraphics.FillRectangle(Brushes.White, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))                            oCheckbox.DrawToBitmap(oBitmap, New Rectangle(CType((oBitmap.Width - oCheckbox.Width) / 2, Int32), CType((oBitmap.Height - oCheckbox.Height) / 2, Int32), oCheckbox.Width, oCheckbox.Height))                            e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))                         ElseIf oColumnTypes(i) Is GetType(DataGridViewComboBoxColumn) Then                             oComboBox.Size = New Size(oColumnWidths(i), nHeight)                            Dim oBitmap As New Bitmap(oComboBox.Width, oComboBox.Height)                            oComboBox.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))                            e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))                            e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i) + 1, nTop, oColumnWidths(i) - 16, nHeight), oStringFormatComboBox)                         ElseIf oColumnTypes(i) Is GetType(DataGridViewImageColumn) Then                             Dim oCellSize As Rectangle = New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight)                            Dim oImageSize As Size = CType(oCell.Value, Image).Size                            e.Graphics.DrawImage(oCell.Value, New Rectangle(oColumnLefts(i) + CType(((oCellSize.Width - oImageSize.Width) / 2), Int32), nTop + CType(((oCellSize.Height - oImageSize.Height) / 2), Int32), CType(oCell.Value, Image).Width, CType(oCell.Value, Image).Height))                         End If                         e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))                         i += 1                     Next                 End If                 nRowPos += 1                nRowsPerPage += 1             Loop             DrawFooter(e, nRowsPerPage)             e.HasMorePages = False     End Sub     Private Sub DrawFooter(ByVal e As System.Drawing.Printing.PrintPageEventArgs, ByVal RowsPerPage As Int32)         Dim sPageNo As String = nPageNo.ToString + " of " + Math.Ceiling(DataGridView1.Rows.Count / RowsPerPage).ToString         ' Right Align - User Name        e.Graphics.DrawString(sUserName, DataGridView1.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, DataGridView1.Font, e.MarginBounds.Width).Width), e.MarginBounds.Top + e.MarginBounds.Height + 7)         ' Left Align - Date/Time        e.Graphics.DrawString(Now.ToLongDateString + " " + Now.ToShortTimeString, DataGridView1.Font, Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top + e.MarginBounds.Height + 7)         ' Center  - Page No. Info        e.Graphics.DrawString(sPageNo, DataGridView1.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, DataGridView1.Font, e.MarginBounds.Width).Width) / 2, e.MarginBounds.Top + e.MarginBounds.Height + 31)     End Sub
 

Answer 65

Will, This is great code. Thank you!!! This works great for a straight print. I've played around with the code  but can't seem to get it to work with print  preview or a printdialog control. Do you have any code or have any idea on how to modofy your code so that it works with either control???   Thanks, VB-Bandit
 

Answer 66

VB-Bandit,

The code  above creates the PrintDocument now all you need to do is use it, the following code with give you a print  preview!

Dim dlg AsNew PrintPreviewDialog()

dlg.Document = PrintDocument1

dlg.ShowDialog()

This code gives you the page setup form...

Dim psDlg AsNew PageSetupDialog

Dim storedPageSettings As PageSettings = New PageSettings()

psDlg.PageSettings = storedPageSettings

psDlg.ShowDialog()

I hope this is what you were looking for!

CoNNect

 

Answer 67

Thanks Heaps for your code  Will!!! BTW, your code drops off the last line, it's fixed now as below:  
 

Answer 68

Private oStringFormat As StringFormat
    Private oStringFormatComboBox As StringFormat
    Private oButton As Button
    Private oCheckbox As CheckBox
    Private oComboBox As ComboBox

    Private nTotalWidth As Int16
    Private nRowPos As Int16
    Private NewPage As Boolean
    Private nPageNo As Int16
    Private Header As String = "Header Test"
    Private sUserName As String = "Will"

    Private Sub PrintDocument1_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.BeginPrint

        oStringFormat = New StringFormat
        oStringFormat.Alignment = StringAlignment.Near
        oStringFormat.LineAlignment = StringAlignment.Center
        oStringFormat.Trimming = StringTrimming.EllipsisCharacter

        oStringFormatComboBox = New StringFormat
        oStringFormatComboBox.LineAlignment = StringAlignment.Center
        oStringFormatComboBox.FormatFlags = StringFormatFlags.NoWrap
        oStringFormatComboBox.Trimming = StringTrimming.EllipsisCharacter

        oButton = New Button
        oCheckbox = New CheckBox
        oComboBox = New ComboBox

        nTotalWidth = 0
        For Each oColumn As DataGridViewColumn In DataGridView1.Columns

            nTotalWidth += oColumn.Width

        Next
        nPageNo = 1
        NewPage = True
        nRowPos = 0

    End Sub

    Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage

            Static oColumnLefts As New ArrayList
            Static oColumnWidths As New ArrayList
            Static oColumnTypes As New ArrayList
            Static nHeight As Int16

            Dim nWidth, i, nRowsPerPage As Int16
            Dim nTop As Int16 = e.MarginBounds.Top
            Dim nLeft As Int16 = e.MarginBounds.Left

            If nPageNo = 1 Then

                For Each oColumn As DataGridViewColumn In DataGridView1.Columns

                    nWidth = CType(Math.Floor(oColumn.Width / nTotalWidth * nTotalWidth * (e.MarginBounds.Width / nTotalWidth)), Int16)

                    nHeight = e.Graphics.MeasureString(oColumn.HeaderText, oColumn.InheritedStyle.Font, nWidth).Height + 11

                    oColumnLefts.Add(nLeft)
                    oColumnWidths.Add(nWidth)
                    oColumnTypes.add(oColumn.GetType)
                    nLeft += nWidth

                Next

            End If

            Do While nRowPos < DataGridView1.Rows.Count - 1

                Dim oRow As DataGridViewRow = DataGridView1.Rows(nRowPos)

                If nTop + nHeight >= e.MarginBounds.Height + e.MarginBounds.Top Then

                    DrawFooter(e, nRowsPerPage)

                    NewPage = True
                    nPageNo += 1
                    e.HasMorePages = True
                    Exit Sub

                Else

                    If NewPage Then

                        ' Draw Header
                        e.Graphics.DrawString(Header, New Font(DataGridView1.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top - e.Graphics.MeasureString(Header, New Font(DataGridView1.Font, FontStyle.Bold), e.MarginBounds.Width).Height - 13)

                        ' Draw Columns
                        nTop = e.MarginBounds.Top
                        i = 0
                        For Each oColumn As DataGridViewColumn In DataGridView1.Columns

                            e.Graphics.FillRectangle(New SolidBrush(Drawing.Color.LightGray), New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
                            e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))
                            e.Graphics.DrawString(oColumn.HeaderText, oColumn.InheritedStyle.Font, New SolidBrush(oColumn.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)
                            i += 1

                        Next
                        NewPage = False

                    End If

                    nTop += nHeight
                    i = 0
                    For Each oCell As DataGridViewCell In oRow.Cells

                        If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then

                            e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)

                        ElseIf oColumnTypes(i) Is GetType(DataGridViewButtonColumn) Then

                            oButton.Text = oCell.Value.ToString
                            oButton.Size = New Size(oColumnWidths(i), nHeight)
                            Dim oBitmap As New Bitmap(oButton.Width, oButton.Height)
                            oButton.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
                            e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))

                        ElseIf oColumnTypes(i) Is GetType(DataGridViewCheckBoxColumn) Then

                            oCheckbox.Size = New Size(14, 14)
                            oCheckbox.Checked = CType(oCell.Value, Boolean)
                            Dim oBitmap As New Bitmap(oColumnWidths(i), nHeight)
                            Dim oTempGraphics As Graphics = Graphics.FromImage(oBitmap)
                            oTempGraphics.FillRectangle(Brushes.White, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
                            oCheckbox.DrawToBitmap(oBitmap, New Rectangle(CType((oBitmap.Width - oCheckbox.Width) / 2, Int32), CType((oBitmap.Height - oCheckbox.Height) / 2, Int32), oCheckbox.Width, oCheckbox.Height))
                            e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))

                        ElseIf oColumnTypes(i) Is GetType(DataGridViewComboBoxColumn) Then

                            oComboBox.Size = New Size(oColumnWidths(i), nHeight)
                            Dim oBitmap As New Bitmap(oComboBox.Width, oComboBox.Height)
                            oComboBox.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
                            e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))
                            e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i) + 1, nTop, oColumnWidths(i) - 16, nHeight), oStringFormatComboBox)

                        ElseIf oColumnTypes(i) Is GetType(DataGridViewImageColumn) Then

                            Dim oCellSize As Rectangle = New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight)
                            Dim oImageSize As Size = CType(oCell.Value, Image).Size
                            e.Graphics.DrawImage(oCell.Value, New Rectangle(oColumnLefts(i) + CType(((oCellSize.Width - oImageSize.Width) / 2), Int32), nTop + CType(((oCellSize.Height - oImageSize.Height) / 2), Int32), CType(oCell.Value, Image).Width, CType(oCell.Value, Image).Height))

                        End If

                        e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))

                        i += 1

                    Next

                End If

                nRowPos += 1
                nRowsPerPage += 1

            Loop

            DrawFooter(e, nRowsPerPage)

            e.HasMorePages = False

    End Sub

    Private Sub DrawFooter(ByVal e As System.Drawing.Printing.PrintPageEventArgs, ByVal RowsPerPage As Int32)

        Dim sPageNo As String = nPageNo.ToString + " of " + Math.Ceiling(DataGridView1.Rows.Count / RowsPerPage).ToString

        ' Right Align - User Name
        e.Graphics.DrawString(sUserName, DataGridView1.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, DataGridView1.Font, e.MarginBounds.Width).Width), e.MarginBounds.Top + e.MarginBounds.Height + 7)

        ' Left Align - Date/Time
        e.Graphics.DrawString(Now.ToLongDateString + " " + Now.ToShortTimeString, DataGridView1.Font, Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top + e.MarginBounds.Height + 7)

        ' Center  - Page No. Info
        e.Graphics.DrawString(sPageNo, DataGridView1.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, DataGridView1.Font, e.MarginBounds.Width).Width) / 2, e.MarginBounds.Top + e.MarginBounds.Height + 31)

    End Sub

 

Answer 69

Hy guys.

I must say that this is a great code. But i get following error
Error 1 Handles clause requires a WithEvents variable defined in the containing type or one of its base types.

Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage

Problem is with Handles PrintDocument1.PrintPage

Can you please tell me what i'm doing wrong?

Regards...
 

Answer 70

Ok i managed to solve that. But now i got one serious problem! This code print  all rows from my DataGridView except last one. It always show one page more that actually exist.

I have try your code  too CoNNect but there is same problem with last row...


Some help will be very wellcome!
 

Answer 71

Ok i have managed that too. If anyone will run into similar problem here is a way to set it right.

In while loop in posted code  you must set Do While nRowPos < DataGridView1.Rows.Count - 1 you must delet -1. It should look like thisDo While nRowPos < DataGridView1.Rows.Count. Then it will work just fine.

Great code indeed. Thank you...

 

Answer 72

This code  was a HUGE help.  Thank you... I did add/change the following because I had a few empty cells and I was getting errors For Each oCell As DataGridViewCell In oRow.Cells If oCell.Value <> Nothing Then sValue = oCell.Value.ToString else sValue = "" End If If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then e.Graphics.DrawString(sValue, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), oStringFormat)
 

Answer 73

Hey, That's great.  I had the same problem and would like to know how you did.  I tried but not as lucky as you.  Help please!
 

Answer 74

is your problem about two pages on the same page?
 

Answer 75

If anyone is interested, I converted the code  to C# and added a fix for correctly computing number of pages on the last page.

privateStringFormat m_stringFormat;

privatedouble m_totalWidth;

privateint m_rowPos;

privatebool m_newPage;

privateint m_pageNo;

privatestring m_pageHeader = "Header";

privatestring m_userName = "Printed by <username>";

privateArrayList m_columnLefts = newArrayList();

privateArrayList m_columnWidths = newArrayList();

privateint m_pageHeight = 0;

privateint m_pageCount = 0;

privatevoid printDocument1_BeginPrint(object sender, System.Drawing.Printing.PrintEventArgs e)

{

m_stringFormat = newStringFormat();

m_stringFormat.Alignment = StringAlignment.Near;

m_stringFormat.LineAlignment = StringAlignment.Center;

m_stringFormat.Trimming = StringTrimming.EllipsisCharacter;

m_totalWidth = 0;

foreach (DataGridViewColumn oColumn in dataGridView1.Columns)

{

m_totalWidth += oColumn.Width;

}

m_pageNo = 1;

m_newPage = true;

m_rowPos = 0;

}

privatevoid printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)

{

int nWidth, i;

double nRowsPerPage = 0;

int nTop = e.MarginBounds.Top;

int nLeft = e.MarginBounds.Left;

if (m_pageNo == 1)

{

m_columnLefts.Clear();

m_columnWidths.Clear();

m_pageHeight = 0;

m_pageCount = 0;

foreach (DataGridViewColumn oColumn in dataGridView1.Columns)

{

double floorVal = Convert.ToDouble( oColumn.Width ) / m_totalWidth * m_totalWidth * (Convert.ToDouble( e.MarginBounds.Width) / m_totalWidth);

nWidth = Convert.ToInt32(Math.Floor(floorVal));

m_pageHeight = Convert.ToInt32(e.Graphics.MeasureString(oColumn.HeaderText, oColumn.InheritedStyle.Font, nWidth).Height) + 11;

m_columnLefts.Add(nLeft);

m_columnWidths.Add(nWidth);

nLeft += nWidth;

}

}

while (m_rowPos < dataGridView1.Rows.Count )

{

DataGridViewRow oRow = dataGridView1.Rows[m_rowPos];

if (nTop + m_pageHeight >= e.MarginBounds.Height + e.MarginBounds.Top)

{

DrawFooter(e, nRowsPerPage);

m_newPage = true;

m_pageNo++;

e.HasMorePages = true;

return;

}

else

{

if (m_newPage)

{

// Draw Header

e.Graphics.DrawString(m_pageHeader, newFont(dataGridView1.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top - e.Graphics.MeasureString(m_pageHeader, newFont(dataGridView1.Font, FontStyle.Bold), e.MarginBounds.Width).Height - 13);

// Draw Columns

nTop = e.MarginBounds.Top;

i = 0;

foreach (DataGridViewColumn oColumn in dataGridView1.Columns)

{

e.Graphics.FillRectangle(newSolidBrush(Color.LightGray), newRectangle((int)m_columnLeftsIdea, nTop, (int)m_columnWidthsIdea, m_pageHeight));

e.Graphics.DrawRectangle(Pens.Black, newRectangle((int)m_columnLeftsIdea, nTop, (int)m_columnWidthsIdea, m_pageHeight));

e.Graphics.DrawString(oColumn.HeaderText, oColumn.InheritedStyle.Font, newSolidBrush(oColumn.InheritedStyle.ForeColor), newRectangleF((int)m_columnLeftsIdea, nTop, (int)m_columnWidthsIdea, m_pageHeight), m_stringFormat);

i++;

}

m_newPage = false;

}

nTop += m_pageHeight;

i = 0;

foreach (DataGridViewCell oCell in oRow.Cells)

{

string sValue = String.Empty;

if (oCell.Value != null)

{

sValue = oCell.Value.ToString();

}

e.Graphics.DrawString(sValue, oCell.InheritedStyle.Font, newSolidBrush(oCell.InheritedStyle.ForeColor), newRectangleF((int)m_columnLeftsIdea, nTop, (int)m_columnWidthsIdea, m_pageHeight), m_stringFormat);

e.Graphics.DrawRectangle(Pens.Black, newRectangle((int)m_columnLeftsIdea, nTop, (int)m_columnWidthsIdea, m_pageHeight));

i++;

}

}

m_rowPos++;

nRowsPerPage++;

}

DrawFooter(e, nRowsPerPage);

e.HasMorePages = false;

}

privatevoid DrawFooter(System.Drawing.Printing.PrintPageEventArgs e, double nRowsPerPage)

{

if (m_pageCount == 0)

{

m_pageCount = Convert.ToInt32( Math.Ceiling(Convert.ToDouble(dataGridView1.Rows.Count) / nRowsPerPage) );

}

string sPageNo = String.Format("Page {0} of {1}", m_pageNo.ToString(), m_pageCount.ToString()).ToString();

// Right Align - User Name

e.Graphics.DrawString(m_userName, dataGridView1.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, dataGridView1.Font, e.MarginBounds.Width).Width), e.MarginBounds.Top + e.MarginBounds.Height + 7);

// Left Align - Date/Time

e.Graphics.DrawString(DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToShortTimeString(), dataGridView1.Font, Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top + e.MarginBounds.Height + 7);

// Center - Page No. Info

e.Graphics.DrawString(sPageNo, dataGridView1.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, dataGridView1.Font, e.MarginBounds.Width).Width) / 2, e.MarginBounds.Top + e.MarginBounds.Height + 31);

}

 

Answer 76

JeremyZK wrote:

If oCell.Value <> NothingThen

Love the code!

One small change to handle dbnull:

If oCell.Value IsNot Nothing Then

or

If Not oCell.Value Is Nothing Then

 

Answer 77

Hi,

Have a look to this article 'DataGridViewPrinter Class':

http://www.codeproject.com/csharp/datagridviewprinter.asp


Salan

 

Answer 78

Hi,

Great Code! I Try to modify it because I need that it don't print  a column if the property visible is set to false ... but I can't resolve the problem!

Anyone can help me?! Thanks so much :)

P.S. I Apologise for my bad english!

 

Answer 79

Hi Frankie,

Next time if you have question regarding the DataGridViewPrinter class, try to post it in the article page of that class:

http://www.codeproject.com/csharp/datagridviewprinter.asp

However, to solve your problem, just insert the below code  in the beginning of the Calculate function of the class:

foreach (DataGridViewColumn col in TheDataGridView.Columns)

    col.Visible = true;

Salan..

 

Answer 80

Excellent piece of code, does exactly what it is supposed to do, did have problem with not displaying last row but the deleteing of the -1 off count fixed problem. Thank you
 

Answer 81

After reading this post, I decided to give it the Print Grid solution a try (by will_affinity).  I was able to get it to work.  The Print Preview, Print Dialog, and Page Setup all worked as advertised, but I did rub into a slight problem that I am hoping someone in this discussion board can help me with.

If I select Print Preview, then close that window and select Page Setup and Perform another Print Preview, the grid maintains the same width as in Portrait.  Whereas, if I start the program over, select Page Setup, change to Landscape, select Print Preview (document looks ok), select Page Setup, select Portrait, select Print Preview (document looks good), select Page Setup, change to Landscape, select Print Preview (document has bad margins again).

I'm sure this is not the best way to discribe what is happening, but since I am not to sure what I need to look for ...Oh well.  I guess I sound confused and lost because I am.  I have only been using Visual Basic (VS 2005) for about 6 months now, and I know I've only scratched the surface on what this stuff is capable of.  Anyway, any help, comments, or directions would be greatly appreciated.  Thank you in advance for your time and effort.

 

Answer 82

There's a problem with printing  out the footer. It messes up the page number if the page has fewer than the max number of rows. For example, I had 38 rows spread over two pages, the first page said "Page 1 of 2" but the last one would say "Page 2 of 13" since there were only 3 rows on the final page. Either way, I've 'Option Stricted' and turned it into a class unto itself. Enjoy!

To Implement:
    Private Sub btnPrintPreview_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPrintPreview.Click
        If IsNothing(Printer) Then
            Printer = New Printer(dgvJobs, Me.Text, gblUserName) 'DataGridView, Wiindow Title (as the Page Header), Username
        End If
        Printer.ShowPrintPreviewDialog()
    End Sub

    Private Sub btnPrint_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPrint.Click
        If IsNothing(Printer) Then
            Printer = New Printer(dgvJobs, Me.Text, gblUserName) 'DataGridView, Wiindow Title (as the Page Header), Username
        End If
        Printer.Print()
    End Sub

Public Class Printer
    Private oStringFormat As StringFormat
    Private oStringFormatComboBox As StringFormat
    Private oButton As Button
    Private oCheckbox As CheckBox
    Private oComboBox As ComboBox

    Private nTotalWidth As Int16
    Private nRowPos As Int16
    Private NewPage As Boolean
    Private nPageNo As Int16
    Private Header As String
    Private sUserName As String
    Private nPageCount As Integer = 0
    Private dgv As DataGridView
    Private WithEvents PrintDoc As New Printing.PrintDocument
    Private storedPageSettings As Printing.PageSettings = New Printing.PageSettings()

    Property DataGridViewToPrint() As DataGridView
        Get
            Return dgv
        End Get
        Set(ByVal value As DataGridView)
            dgv = value
        End Set
    End Property
    Property UserName() As String
        Get
            Return sUserName
        End Get
        Set(ByVal value As String)
            sUserName = value
        End Set
    End Property
    Property HeaderText() As String
        Get
            Return Header
        End Get
        Set(ByVal value As String)
            Header = value
        End Set
    End Property

    Public Sub New(ByVal aDGV As DataGridView, ByVal aHeader As String, ByVal aUserName As String)
        DataGridViewToPrint = aDGV
        UserName = aUserName
        HeaderText = aHeader
    End Sub
    Public Sub Print()
        Dim psDlg As New PageSetupDialog
        psDlg.PageSettings = storedPageSettings
        psDlg.ShowDialog()
    End Sub
    Public Sub ShowPrintPreviewDialog()
        Dim dlg As New PrintPreviewDialog()
        dlg.Document = PrintDoc
        dlg.ShowDialog()
    End Sub
    Private Sub PrintDoc_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDoc.BeginPrint

        oStringFormat = New StringFormat
        oStringFormat.Alignment = StringAlignment.Near
        oStringFormat.LineAlignment = StringAlignment.Center
        oStringFormat.Trimming = StringTrimming.EllipsisCharacter

        oStringFormatComboBox = New StringFormat
        oStringFormatComboBox.LineAlignment = StringAlignment.Center
        oStringFormatComboBox.FormatFlags = StringFormatFlags.NoWrap
        oStringFormatComboBox.Trimming = StringTrimming.EllipsisCharacter

        oButton = New Button
        oCheckbox = New CheckBox
        oComboBox = New ComboBox

        nTotalWidth = 0
        For Each oColumn As DataGridViewColumn In DataGridViewToPrint.Columns

            nTotalWidth = CShort(nTotalWidth + oColumn.Width)

        Next
        nPageNo = 1
        NewPage = True
        nRowPos = 0

    End Sub

    Private Sub Printdoc_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDoc.PrintPage

        Static oColumnLefts As New ArrayList
        Static oColumnWidths As New ArrayList
        Static oColumnTypes As New ArrayList
        Static nHeight As Int16

        Dim nWidth, i, nRowsPerPage As Int16
        Dim nTop As Int16 = CShort(e.MarginBounds.Top)
        Dim nLeft As Int16 = CShort(e.MarginBounds.Left)

        If nPageNo = 1 Then

            For Each oColumn As DataGridViewColumn In DataGridViewToPrint.Columns

                nWidth = CType(Math.Floor(oColumn.Width / nTotalWidth * nTotalWidth * (e.MarginBounds.Width / nTotalWidth)), Int16)

                nHeight = CShort(e.Graphics.MeasureString(oColumn.HeaderText, oColumn.InheritedStyle.Font, nWidth).Height + 11)

                oColumnLefts.Add(nLeft)
                oColumnWidths.Add(nWidth)
                oColumnTypes.Add(oColumn.GetType)
                nLeft += nWidth

            Next

        End If

        Do While nRowPos < DataGridViewToPrint.Rows.Count

            Dim oRow As DataGridViewRow = DataGridViewToPrint.Rows(nRowPos)

            If nTop + nHeight >= e.MarginBounds.Height + e.MarginBounds.Top Then

                DrawFooter(e, nRowsPerPage)

                NewPage = True
                nPageNo = CShort(nPageNo + 1)
                e.HasMorePages = True
                Exit Sub

            Else

                If NewPage Then

                    ' Draw Header
                    e.Graphics.DrawString(Header, New Font(DataGridViewToPrint.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top - e.Graphics.MeasureString(Header, New Font(DataGridViewToPrint.Font, FontStyle.Bold), e.MarginBounds.Width).Height - 13)

                    ' Draw Columns
                    nTop = CShort(e.MarginBounds.Top)
                    i = 0
                    For Each oColumn As DataGridViewColumn In DataGridViewToPrint.Columns

                        e.Graphics.FillRectangle(New SolidBrush(Drawing.Color.LightGray), New Rectangle(CInt(oColumnLefts(i)), nTop, CInt(oColumnWidths(i)), nHeight))
                        e.Graphics.DrawRectangle(Pens.Black, New Rectangle(CInt(oColumnLefts(i)), nTop, CInt(oColumnWidths(i)), nHeight))
                        e.Graphics.DrawString(oColumn.HeaderText, oColumn.InheritedStyle.Font, New SolidBrush(oColumn.InheritedStyle.ForeColor), New RectangleF(CSng(oColumnLefts(i)), nTop, CSng(oColumnWidths(i)), nHeight), oStringFormat)
                        i = CShort(i + 1)

                    Next
                    NewPage = False

                End If

                nTop += nHeight
                i = 0
                For Each oCell As DataGridViewCell In oRow.Cells

                    If oColumnTypes(i) Is GetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) Is GetType(DataGridViewLinkColumn) Then

                        e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(CSng(oColumnLefts(i)), nTop, CSng(oColumnWidths(i)), nHeight), oStringFormat)

                    ElseIf oColumnTypes(i) Is GetType(DataGridViewButtonColumn) Then

                        oButton.Text = oCell.Value.ToString
                        oButton.Size = New Size(CInt(oColumnWidths(i)), nHeight)
                        Dim oBitmap As New Bitmap(oButton.Width, oButton.Height)
                        oButton.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
                        e.Graphics.DrawImage(oBitmap, New Point(CInt(oColumnLefts(i)), nTop))

                    ElseIf oColumnTypes(i) Is GetType(DataGridViewCheckBoxColumn) Then

                        oCheckbox.Size = New Size(14, 14)
                        oCheckbox.Checked = CType(oCell.Value, Boolean)
                        Dim oBitmap As New Bitmap(CInt(oColumnWidths(i)), nHeight)
                        Dim oTempGraphics As Graphics = Graphics.FromImage(oBitmap)
                        oTempGraphics.FillRectangle(Brushes.White, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
                        oCheckbox.DrawToBitmap(oBitmap, New Rectangle(CType((oBitmap.Width - oCheckbox.Width) / 2, Int32), CType((oBitmap.Height - oCheckbox.Height) / 2, Int32), oCheckbox.Width, oCheckbox.Height))
                        e.Graphics.DrawImage(oBitmap, New Point(CInt(oColumnLefts(i)), nTop))

                    ElseIf oColumnTypes(i) Is GetType(DataGridViewComboBoxColumn) Then

                        oComboBox.Size = New Size(CInt(oColumnWidths(i)), nHeight)
                        Dim oBitmap As New Bitmap(oComboBox.Width, oComboBox.Height)
                        oComboBox.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))
                        e.Graphics.DrawImage(oBitmap, New Point(CInt(oColumnLefts(i)), nTop))
                        e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(CInt(oColumnLefts(i)) + 1, nTop, CInt(oColumnWidths(i)) - 16, nHeight), oStringFormatComboBox)

                    ElseIf oColumnTypes(i) Is GetType(DataGridViewImageColumn) Then

                        Dim oCellSize As Rectangle = New Rectangle(CInt(oColumnLefts(i)), nTop, CInt(oColumnWidths(i)), nHeight)
                        Dim oImageSize As Size = CType(oCell.Value, Image).Size
                        e.Graphics.DrawImage(CType(oCell.Value, Image), New Rectangle(CType(oColumnLefts(i), Int32) + CType(((oCellSize.Width - oImageSize.Width) / 2), Int32), nTop + CType(((oCellSize.Height - oImageSize.Height) / 2), Int32), CType(oCell.Value, Image).Width, CType(oCell.Value, Image).Height))

                    End If

                    e.Graphics.DrawRectangle(Pens.Black, New Rectangle(CInt(oColumnLefts(i)), nTop, CInt(oColumnWidths(i)), nHeight))

                    i = CShort(i + 1)

                Next

            End If

            nRowPos = CShort(nRowPos + 1)
            nRowsPerPage = CShort(nRowsPerPage + 1)
        Loop

        DrawFooter(e, nRowsPerPage)

        e.HasMorePages = False

    End Sub

    Private Sub DrawFooter(ByVal e As System.Drawing.Printing.PrintPageEventArgs, ByVal RowsPerPage As Int32)

        'Changed from Page XXX of XXX to just Page XXX because
        'Math.Ceiling(DataGridViewToPrint.Rows.Count / RowsPerPage).ToString() would generate
        'inaccurate page numbers on pages with less than the max number of rows (ie: the last page)
        'Dim sPageNo As String = nPageNo.ToString + " of " + Math.Ceiling(DataGridViewToPrint.Rows.Count / RowsPerPage).ToString
        Dim sPageNo As String = "Page " + nPageNo.ToString

        ' Right Align - User Name
        e.Graphics.DrawString("Printed by: " + sUserName, DataGridViewToPrint.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, DataGridViewToPrint.Font, e.MarginBounds.Width).Width), e.MarginBounds.Top + e.MarginBounds.Height + 7)

        ' Left Align - Date/Time
        e.Graphics.DrawString(Now.ToLongDateString + " " + Now.ToShortTimeString, DataGridViewToPrint.Font, Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top + e.MarginBounds.Height + 7)

        ' Center  - Page No. Info
        e.Graphics.DrawString(sPageNo, DataGridViewToPrint.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, DataGridViewToPrint.Font, e.MarginBounds.Width).Width) / 2, e.MarginBounds.Top + e.MarginBounds.Height + 31)

    End Sub
End Class

 

Answer 83

hey,

i tried your code  but it is giving me compiling errors

Error 1 Handles clause requires a WithEvents variable defined in the containing type or one of its base {ERROR OCCURED IN BTN[PREVIEW CLICK EVENT}

Error 2 'Printer' is a type and cannot be used as an expression. {IN THE SAME EVENT :

If IsNothing(Printer) Then

Printer = New Printer(DataGridView1, Me.Text, "shrey") 'DataGridView, Wiindow Title (as the Page Header), Username

EndIf

Printer.ShowPrintPreviewDialog()

}

Error 8 Reference to a non-shared member requires an object reference. 

Printer.Print()

Could you help me i am new at vb.

thnks in advance

Shrey Sharma

 

Answer 84

DrawFooter(e, nPageNo);

after the main row loop rather than

DrawFooter(e, nRowsPerPage);

eliminates the problem when the page has fewer than the max rows too.

 

Answer 85

How do I call this from a button?

Regards

Sabe75

 

Answer 86

Thanks Guys,

Its a really a great code. My heartful Thanks to those guys who did the program. please update for new codings and projects.

vimalbtechit2005@gmail.com

Vimal.

 

Answer 87

Hey I am relativly new to VB.Net, love the code, just one question. I have a DGV with 24 columns, I do not want to print  all the columns  how could I set it up just to print the first 9 columns? Please help thanks in advance!
 

Answer 88

Dim sPageNo As String = nPageNo.ToString + " of " + Math.Ceiling(DataGridViewToPrint.Rows.Count / RowsPerPage).ToString


I changed the above code  in Sub DrawFooter  to:

________________________________________________________________________

Dim sPageNo AsString

If blnGotNumPages = FalseThen

blnGotNumPages = True

strNumOfPages = Math.Ceiling(DataGridView1.Rows.Count / RowsPerPage).ToString

sPageNo = nPageNo.ToString + " of " + Math.Ceiling(DataGridView1.Rows.Count / RowsPerPage).ToString

Else

sPageNo = nPageNo.ToString + " of " + strNumOfPages

EndIf

______________________________________________________________________________________________

Ofcourse I declared blnGotNumPages and strNumOfPages outside of the Sub, and made blnGotNumPages = False when the print  Preview btn was clicked.

This solution will give you Page x of y correctly. Even for the last page. I hope this was helpful to some of you all.

Thomas

 

Answer 89

Getting the same errors, did anyone figure it out?
Printer is a class. Cant imagine why it would bring the error:

'Printer' is a type and cannot be used as an expression.

Thanks.
 

Answer 90

Hi,

Hi, I like the code  and I also saw the code project printing  class. Here is a version that uses static methods and auto generates the print  document internally. This way you can just call: PrintFactory.Print() or PrintFactory.Preview() from anywhere and not worry about instances. Obviously, you can expand on this code in a million ways, but it is start for clean library for datagridview  printing.

Imports System.Windows.Forms

PublicClass PrintFactory

#Region"Instance"

#Region"Declerations"

PrivateWithEvents _printDocument As Printing.PrintDocument = _

New Printing.PrintDocument()

Private _dgv As DataGridView

Private _stringFormat As StringFormat

Private _stringFormatComboBox As StringFormat

Private _button As Button

Private _checkBox As CheckBox

Private _comboBox As ComboBox

Private _totalWidth As Int16

Private _rowPos As Int16

Private _newPage AsBoolean

Private _pageNumber As Int16

Private _userName AsString

Private _headerText AsString

#EndRegion

#Region"Properties"

PrivateReadOnlyProperty DGV() As DataGridView

Get

Return _dgv

EndGet

EndProperty

PrivateProperty HeaderText() AsString

Get

Return _headerText

EndGet

Set(ByVal value AsString)

_headerText = value

EndSet

EndProperty

PrivateProperty UserName() AsString

Get

Return _userName

EndGet

Set(ByVal value AsString)

_userName = value

EndSet

EndProperty

PrivateProperty StringFormat() As StringFormat

Get

Return _stringFormat

EndGet

Set(ByVal value As StringFormat)

_stringFormat = value

EndSet

EndProperty

PrivateProperty StringFormatComboBox() As StringFormat

Get

Return _stringFormatComboBox

EndGet

Set(ByVal value As StringFormat)

_stringFormatComboBox = value

EndSet

EndProperty

PrivateProperty Button() As Button

Get

Return _button

EndGet

Set(ByVal value As Button)

_button = value

EndSet

EndProperty

PrivateProperty CheckBox() As CheckBox

Get

Return _checkBox

EndGet

Set(ByVal value As CheckBox)

_checkBox = value

EndSet

EndProperty

PrivateProperty ComboBox() As ComboBox

Get

Return _comboBox

EndGet

Set(ByVal value As ComboBox)

_comboBox = value

EndSet

EndProperty

PrivateProperty TotalWidth() As Int16

Get

Return _totalWidth

EndGet

Set(ByVal value As Int16)

_totalWidth = value

EndSet

EndProperty

PrivateProperty RowPos() As Int16

Get

Return _rowPos

EndGet

Set(ByVal value As Int16)

_rowPos = value

EndSet

EndProperty

PrivateProperty NewPage() AsBoolean

Get

Return _newPage

EndGet

Set(ByVal value AsBoolean)

_newPage = value

EndSet

EndProperty

PrivateProperty PageNumber() As Int16

Get

Return _pageNumber

EndGet

Set(ByVal value As Int16)

_pageNumber = value

EndSet

EndProperty

#EndRegion

PrivateSubNew(ByVal userName AsString, _

ByVal headerText AsString)

Me._userName = userName

Me._headerText = headerText

EndSub

PrivateSub _printDocument_PrintPage(ByVal sender AsObject, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles _printDocument.PrintPage

EndPrint(Me, e)

EndSub

#EndRegion

#Region"Statics"

PublicSharedFunction Print(ByVal dgv As DataGridView, _

ByVal userName AsString, _

ByVal headerText AsString) AsBoolean

Validate(dgv, userName, headerText)

Dim tempPrintFactory As PrintFactory = BeginPrint(dgv, userName, headerText)

tempPrintFactory._printDocument.Print()

EndFunction

PublicSharedFunction Preview(ByVal dgv As DataGridView, _

ByVal userName AsString, _

ByVal headerText AsString) AsBoolean

Validate(dgv, userName, headerText)

Dim tempPrintFactory As PrintFactory = BeginPrint(dgv, userName, headerText)

Dim tempPrintDiag AsNew PrintPreviewDialog()

tempPrintDiag.Document = tempPrintFactory._printDocument

tempPrintDiag.ShowDialog()

EndFunction

PrivateSharedFunction BeginPrint(ByVal dgv As DataGridView, ByVal userName AsString, ByVal headerText AsString) As PrintFactory

Dim printEntity As PrintFactory = New PrintFactory(userName, headerText)

printEntity._dgv = dgv

printEntity.StringFormat = New StringFormat

printEntity.StringFormat.Alignment = StringAlignment.Near

printEntity.StringFormat.LineAlignment = StringAlignment.Center

printEntity.StringFormat.Trimming = StringTrimming.EllipsisCharacter

printEntity.StringFormatComboBox = New StringFormat

printEntity.StringFormatComboBox.LineAlignment = StringAlignment.Center

printEntity.StringFormatComboBox.FormatFlags = StringFormatFlags.NoWrap

printEntity.StringFormatComboBox.Trimming = StringTrimming.EllipsisCharacter

printEntity.Button = New Button

printEntity.CheckBox = New CheckBox

printEntity.ComboBox = New ComboBox

printEntity.TotalWidth = 0

ForEach oColumn As DataGridViewColumn In dgv.Columns

printEntity.TotalWidth += oColumn.Width

Next

printEntity.PageNumber = 1

printEntity.NewPage = True

printEntity.RowPos = 0

Return printEntity

EndFunction

PrivateSharedFunction EndPrint(ByVal printEntity As PrintFactory, _

ByVal e As System.Drawing.Printing.PrintPageEventArgs) AsBoolean

Dim oColumnLefts AsNew ArrayList

Dim oColumnWidths AsNew ArrayList

Dim oColumnTypes AsNew ArrayList

Dim nHeight As Int16

Dim nWidth, i, nRowsPerPage As Int16

Dim nTop As Int16 = e.MarginBounds.Top

Dim nLeft As Int16 = e.MarginBounds.Left

If printEntity.PageNumber = 1 Then

ForEach oColumn As DataGridViewColumn In printEntity.DGV.Columns

nWidth = CType(Math.Floor(oColumn.Width / printEntity.TotalWidth * printEntity.TotalWidth * (e.MarginBounds.Width / printEntity.TotalWidth)), Int16)

nHeight = e.Graphics.MeasureString(oColumn.HeaderText, oColumn.InheritedStyle.Font, nWidth).Height + 11

oColumnLefts.Add(nLeft)

oColumnWidths.Add(nWidth)

oColumnTypes.Add(oColumn.GetType)

nLeft += nWidth

Next

EndIf

DoWhile printEntity.RowPos < printEntity.DGV.Rows.Count - 1

Dim oRow As DataGridViewRow = printEntity.DGV.Rows(printEntity.RowPos)

If nTop + nHeight >= e.MarginBounds.Height + e.MarginBounds.Top Then

DrawFooter(printEntity.DGV, printEntity, nRowsPerPage, e)

printEntity.NewPage = True

printEntity.PageNumber += 1

e.HasMorePages = True

ExitFunction

Else

If printEntity.NewPage Then

' Draw Header

e.Graphics.DrawString(printEntity.HeaderText, New Font(printEntity.DGV.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top - e.Graphics.MeasureString(printEntity.HeaderText, New Font(printEntity.DGV.Font, FontStyle.Bold), e.MarginBounds.Width).Height - 13)

' Draw Columns

nTop = e.MarginBounds.Top

i = 0

ForEach oColumn As DataGridViewColumn In printEntity.DGV.Columns

e.Graphics.FillRectangle(New SolidBrush(Drawing.Color.LightGray), New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))

e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))

e.Graphics.DrawString(oColumn.HeaderText, oColumn.InheritedStyle.Font, New SolidBrush(oColumn.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), printEntity.StringFormat)

i += 1

Next

printEntity.NewPage = False

EndIf

nTop += nHeight

i = 0

ForEach oCell As DataGridViewCell In oRow.Cells

If oColumnTypes(i) IsGetType(DataGridViewTextBoxColumn) OrElse oColumnTypes(i) IsGetType(DataGridViewLinkColumn) Then

e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), printEntity.StringFormat)

ElseIf oColumnTypes(i) IsGetType(DataGridViewButtonColumn) Then

printEntity.Button.Text = oCell.Value.ToString

printEntity.Button.Size = New Size(oColumnWidths(i), nHeight)

Dim oBitmap AsNew Bitmap(printEntity.Button.Width, printEntity.Button.Height)

printEntity.Button.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))

e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))

ElseIf oColumnTypes(i) IsGetType(DataGridViewCheckBoxColumn) Then

printEntity.CheckBox.Size = New Size(14, 14)

printEntity.CheckBox.Checked = CType(oCell.Value, Boolean)

Dim oBitmap AsNew Bitmap(oColumnWidths(i), nHeight)

Dim oTempGraphics As Graphics = Graphics.FromImage(oBitmap)

oTempGraphics.FillRectangle(Brushes.White, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))

printEntity.CheckBox.DrawToBitmap(oBitmap, New Rectangle(CType((oBitmap.Width - printEntity.CheckBox.Width) / 2, Int32), CType((oBitmap.Height - printEntity.CheckBox.Height) / 2, Int32), printEntity.CheckBox.Width, printEntity.CheckBox.Height))

e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))

ElseIf oColumnTypes(i) IsGetType(DataGridViewComboBoxColumn) Then

printEntity.ComboBox.Size = New Size(oColumnWidths(i), nHeight)

Dim oBitmap AsNew Bitmap(printEntity.ComboBox.Width, printEntity.ComboBox.Height)

printEntity.ComboBox.DrawToBitmap(oBitmap, New Rectangle(0, 0, oBitmap.Width, oBitmap.Height))

e.Graphics.DrawImage(oBitmap, New Point(oColumnLefts(i), nTop))

e.Graphics.DrawString(oCell.Value.ToString, oCell.InheritedStyle.Font, New SolidBrush(oCell.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i) + 1, nTop, oColumnWidths(i) - 16, nHeight), printEntity.StringFormatComboBox)

ElseIf oColumnTypes(i) IsGetType(DataGridViewImageColumn) Then

Dim oCellSize As Rectangle = New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight)

Dim oImageSize As Size = CType(oCell.Value, Image).Size

e.Graphics.DrawImage(oCell.Value, New Rectangle(oColumnLefts(i) + CType(((oCellSize.Width - oImageSize.Width) / 2), Int32), nTop + CType(((oCellSize.Height - oImageSize.Height) / 2), Int32), CType(oCell.Value, Image).Width, CType(oCell.Value, Image).Height))

EndIf

e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))

i += 1

Next

EndIf

printEntity.RowPos += 1

nRowsPerPage += 1

Loop

DrawFooter(printEntity.DGV, printEntity, nRowsPerPage, e)

e.HasMorePages = False

EndFunction

PrivateSharedFunction DrawFooter(ByVal dgv As DataGridView, _

ByVal printEntity As PrintFactory, _

ByVal RowsPerPage As Int32, _

ByVal e As System.Drawing.Printing.PrintPageEventArgs) AsBoolean

Dim sPageNo AsString = printEntity.PageNumber.ToString + " of " + Math.Ceiling(dgv.Rows.Count / RowsPerPage).ToString

' Right Align - User Name

e.Graphics.DrawString(printEntity.UserName, dgv.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, dgv.Font, e.MarginBounds.Width).Width), e.MarginBounds.Top + e.MarginBounds.Height + 7)

' Left Align - Date/Time

e.Graphics.DrawString(Now.ToLongDateString + " " + Now.ToShortTimeString, dgv.Font, Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top + e.MarginBounds.Height + 7)

' Center - Page No. Info

e.Graphics.DrawString(sPageNo, dgv.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sPageNo, dgv.Font, e.MarginBounds.Width).Width) / 2, e.MarginBounds.Top + e.MarginBounds.Height + 31)

EndFunction

PrivateSharedSub Validate(ByVal dgv As DataGridView, _

ByVal userName AsString, _

ByVal headerText AsString)

If dgv IsNothingThen

ThrowNew ArgumentNullException("dgv")

EndIf

IfString.IsNullOrEmpty(userName) = TrueThen

ThrowNew ArgumentNullException("userName")

EndIf

IfString.IsNullOrEmpty(headerText) = TrueThen

ThrowNew ArgumentNullException("headerText")

EndIf

EndSub

#EndRegion

EndClass

 

Answer 91

I like this code  but I seem to be having issues with an error.  Have you experienced this one.

Index was out of range. Must be non-negative and less than the size of the collection.
The error is in the EndPrint function.

ForEach oColumn As DataGridViewColumn In printEntity.DGV.Columns

Error in this line >>>> e.Graphics.FillRectangle(New SolidBrush(Drawing.Color.LightGray), New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))

e.Graphics.DrawRectangle(Pens.Black, New Rectangle(oColumnLefts(i), nTop, oColumnWidths(i), nHeight))

e.Graphics.DrawString(oColumn.HeaderText, oColumn.InheritedStyle.Font, New SolidBrush(oColumn.InheritedStyle.ForeColor), New RectangleF(oColumnLefts(i), nTop, oColumnWidths(i), nHeight), printEntity.StringFormat)

i += 1

Next

 

Answer 92

 Hi,

 I have tried your code. It is working very well. I wanted one enhancement in that.

 I tried even but that code  after modification seems to be meshy. If you please look into what is my requirement and yes how it would be adjusted in the similar code.

The requirement is : It should print  the grid element like excel which means it should split the column after it reaches to page bounds.

 

Answer 93

sorry, it doesn't solve the problem.

what I do it just change a little code  in "Sub Printdoc_PrintPage"

from

DoWhile nRowPos < DataGridViewToPrint.Rows.Count

to

DoWhile nRowPos < DataGridViewToPrint.Rows.Count - 1

 

Answer 94

Thanks to all that have contributed to this code.

I had an issue with Forkbeard's code  and the hardcopy document not actually printing.

So I changed the "Print" subrouting in the above code to:-

Code Snippet

PublicSub Print()

' Remmed srowan 20070403. Forkbeard's original code posted to MSDN forum is below and commented.

'Dim psDlg As New PageSetupDialog

'psDlg.PageSettings = storedPageSettings

'psDlg.ShowDialog()

' Modified srowan 20070403. Above code was not printing  the document. Modified to perform action after showing the dialog. Also changed from Page Setup Dialog to Printer Dialog.

Dim dlg AsNew PrintDialog()

dlg.Document = PrintDoc

Dim result As DialogResult = dlg.ShowDialog()

If (result = System.Windows.Forms.DialogResult.OK) Then

PrintDoc.Print()

EndIf

EndSub

Regards,


Scott

 

Answer 95

hellow!! I am new in VB2005 and i really have no idea about it..My on the job training superior ask me to make a program..I already finish some of the parts except the printing...I only used rich textbox, the copy/paste command the problem is the alignment.

please reply... thanks alot..godbless

 

Answer 96

Just replace

DoWhile nRowPos < DataGridView1.Rows.Count - 1

with

DoWhile nRowPos < DataGridView1.Rows.Count

 

Answer 97

I've got a problem where one of the columns  in the datagridview  displays ONLY the date, but the print  is printing  the date plus '00:00:00'

Can anyone help me please with the code  to displaying only the date in a format of 'dd/mm/yy' to the print document?

Thanks

 

Answer 98

Just starting with VB Express

This helped a lot.

Have found that you need to destroy the static variables when finished or the next time you print  preview it uses the same value even if you change the column width s etc.

Also found that you need to check for actual cell contents before printing  text from a cell.

Easy done.

Great bit of code.
 

Answer 99

The static approach is interesting. Buster has another approach using vb, that prints the grid as seen on the screen.

I've modified it for c# too.

 

Answer 100

hey all. after long time and nearly null results on vb2005 and datagridview  printing. i found this thread.. all works ok with some minor modifications.. but one or two problems still persists.

if too many columns  then it squizes everything in one page.. cant get it on a second.. (not for rows.. but for columns)

and after that. if i preview lets say 5 columns and then 2.. the width of the table gets the whole page.. although its good in the beginning..

any help would be greatly appreciated..

as for the part that wouldnt print  on landscape.. had the same problem as well nd i just got

e.PageSettings.Landscape = True

on the query page settings. or u can even get ur own radiobuttons for the user to have a choice..

thank u in advance

 

Answer 101

FTAO Will_Affinity

Your brain must be the size of a moon. I've copied your code  into my program and it works perfect.

I can't thank you enough, you've saved me hours of headaches. If i could afford it i'd send you a cheque.

NoZparker

 

Answer 102

I'm still having trouble here.

The cell contents is only displaying the date format, which is what I want.

But when I do a print  preview, it displays the date as well as '00:00:00'.

I'd like to remove the time.

Everything else works perfectly.

 

Answer 103

Hi folks, there is a free component that gives the printing  functionality. This is something like pluggin for the DataGridView control itself - it just wraps it - also it gives you the functionalities of searching for an item in the DataGridView control, exporting data to HTML, Excel and Pdf and many more ...

Check it out on http://www.completit.com/Products/DGVE/Overview.aspx

It thing that a lot ot hard work is done there.

 

Answer 104

Was a great post! I just paste it and works! Thank You Very Much
Still I have some question for you. How should I do if I want the Header to be multiline. like:
Title of the page
Subtitle of the page
Another thing where do I put the code  so I can print  it on landscape?
And the last how can I manage the cell borders.
Thats it, than you again for a great code.

 

Answer 105

How did you solve this problem?

 

Answer 106

I started with a need to print  a DataGridView a couple of years ago and went down several pathways. However, I recently discovered a very sweet solution for printing  a DataGridView and many other .Net objects. It is the Reporting Services control available for Visual Studio 2005 (Its also in 2008 but has a nasty bug!). It is an almost trivial task to construct a class to organises the DataGrid contents as a datasource to an RDL (Report Definition Language) based report. The RDL report has good capabilities for formatting, sorting, totalling, etc. Once the report is rendered to the user's screen, the user is able to print it, output to PDF or Excel. A really neat bit is the ability to created a drilldown report which puts more control back into the user's hands.

Do not get confused with server side reporting using Reporting Services. The VS control does not require any SQL Server components or licences. It is described with SQL Server Reporting Services because the RDL syntax and capabilities are almost identical.

 

Answer 107

Does anyone know how to solve the Handles PrintDocument1.PrintPage problem?

Thanks

 

Answer 108

Here you are a tool which can help you: GridDrawer.Net

 

Answer 109

 My datagridveiw works perfect wth the above original code. except with the blank cell whicth returns an error. the above is still great

Thank you.

 

Answer 110

Hi,

Great work and really good one. But One suggetion, is it possible to convert to .NET 2.0.

Why because, Your control will be more usefull, If it is available for .NET 2.0 Applications. Please make it available, then it will be great.

 

Answer 111

How did you fix the previous Handles PrintDocument1.PrintPage problem? I've got the same message.

 

Answer 112

This is great.  One question.  How would i change the page settings so that i could change the paper type.  I would like to be able to use this to print  without a preview.  how would i do that?  thanks!
 

Answer 113

How can i change columns  width (for printing)? some of columns has wraper strings...
 

Answer 114

If my understanding of this is correct You have to change the datagridview  so that you can view the whole collum contents. The code  just looks at the width of the collum that is viewed not the total of the contents. So adjust your collum width of data grid view so that when you see the data on screen you see all of it. Then the print  routine will see the correct width. Hope this helps.

 

Answer 115

I am busy for a few month with a library which could help you to print  DataGridView contents.

see http://www.codeplex.com/PrintDataGridView and enjoy (I hope) Wink

 

Answer 116

Another small fix:

' Right Align - User Name

e.Graphics.DrawString(sUserName, dgv.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(sUserName, dgv.Font, e.MarginBounds.Width).Width), e.MarginBounds.Top + e.MarginBounds.Height + 7)

 

Answer 117

My friend connect . . .

i have a problem. . .

im using vb2008, and your code  works great

but i have one problem with your code :

Dim psDlg AsNew PageSetupDialog

Dim storedPageSettings As PageSettings = New PageSettings()

psDlg.PageSettings = storedPageSettings

psDlg.ShowDialog()

that do not compile, i think there is a typo but i cannot find  where . . .

the vb2008 do not even know pagesettings . . .

so this is my question

a) do you have an updated solution on how to print  a grid from a form?
b) can you fix this code
c) how do i relate the page setupdialog with the print document?

my preview looks good, but the margings are too big, making some columns  display too small

d) id there anyway to hide some columns . . .

Mr. White. . .

 

Answer 118

May be you could try the solution I implemented...

http://www.codeplex.com/PrintYourGridsDotNet

Have a nice evening

 

Answer 119

Private Sub PrintDocument1_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.BeginPrint


Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage



I too am getting the Handles clause requires a WithEvents variable defined in the containing type or one of its base types. error.  Can someone please explain what those of us (there seem to be several) who are getting this message are missing? 
 

Answer 120

I have taken snippits from all over this forum and have been successful in printing  out my datagrid exactly how i want it.

i can print  :-

All

Odds

Evens

Ranges

and Single Pages (all done by the coding)

However, the amount of pages i need to print out are in excess of 300 pages

When I print, the printer only seems to have enough memory for about 100 pages. I then have to start the printing again using the range of pages from say 100 on.

Alternatively in the printer set up I can set the print to print direct, This of coarse sends each page to the printer 1 at a time, which is holding up resources.

Can anyone suggest a solution so that i can print all 300 pages at the same time.

 

Answer 121

Private Sub PrintDocument1_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.BeginPrint

&

Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage

To solve them simply add (double click or drag and drop) a PrintDocument to your project found in the toolbox

For making a Page Setup, followed by a Print Preview Dialog Box that uses your input in the Page Setup you can use this...

'Place these lines after the Public Class (Name of Form)

Public DefaultPageSettings As PageSettings = New PageSettings()

Public StringPageNo AsString

Public StringNumberOfPages AsString

Public BooleanNumOfPages AsBoolean

PrivateSub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

Dim PageSetupDialog1 AsNew PageSetupDialog

PageSetupDialog1.PageSettings = DefaultPageSettings

PageSetupDialog1.ShowDialog()

Dim PrintPreviewDialog1 AsNew PrintPreviewDialog()

BooleanNumberOfPages = False

PrintDocument1.DefaultPageSettings = PageSetupDialog1.PageSettings

PrintPreviewDialog1.Document = PrintDocument1

PrintPreviewDialog1.ShowDialog()

EndSub

'Place these if you a Footer (Page x of y)

If GotNumberOfPages = FalseThen

StringNumberOfPages = Math.Ceiling(DataGridView1.Rows.Count / RowsPerPage).ToString

GotNumberOfPages = True

EndIf

StringPageNo = NumberPageNumber.ToString + " of " + StringNumOfPages

Just remember that the Variables can provide an error if they won't match your project
 
 
 

<< Previous      Next >>


Microsoft   |   Windows   |   Visual Studio   |   Follow us on Twitter