Reputation: 87
I'm having a problem here regarding code I saw posted here: How to print datagridview table with its header in vb.net?
I'm testing without a printer and just saving it as a .pdf file, but it doesn't export the DataGridView
. Can anyone help me? What could be the problem?
As you can see, it is visible in Print Preview:
After I save as pdf (because I don't have printer available to test with):
My code:
Private mRow As Integer = 0
Private newpage As Boolean = True
Private Sub PrintDocument1_PrintPage(sender As Object, e As Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
Dim rect As New Rectangle(12, 9, CInt(PrintDocument1.DefaultPageSettings.PrintableArea.Width), lblCurriculumName.Height)
Dim sf As New StringFormat
sf.Alignment = StringAlignment.Center
sf.LineAlignment = StringAlignment.Center
e.Graphics.DrawString(lblCurriculumName.Text, lblCurriculumName.Font, Brushes.Black, rect, sf)
sf.Alignment = StringAlignment.Center
Dim rect1 As New Rectangle(97, 60, CInt(PrintDocument1.DefaultPageSettings.PrintableArea.Width), txtFullName.Height)
Dim sf1 As New StringFormat
sf1.Alignment = StringAlignment.Near
sf1.LineAlignment = StringAlignment.Near
e.Graphics.DrawString(txtFullName.Text, txtFullName.Font, Brushes.Black, rect1, sf1)
sf1.Alignment = StringAlignment.Center
' sets it to show '...' for long text
Dim fmt As StringFormat = New StringFormat(StringFormatFlags.LineLimit)
fmt.LineAlignment = StringAlignment.Center
fmt.Trimming = StringTrimming.EllipsisCharacter
Dim y As Int32 = e.MarginBounds.Top
Dim rc As Rectangle
Dim x As Int32
Dim h As Int32 = 0
Dim row As DataGridViewRow
' print the header text for a new page
' use a grey bg just like the control
If newpage Then
row = DataGridView1.Rows(mRow)
x = e.MarginBounds.Left
For Each cell As DataGridViewCell In row.Cells
' since we are printing the control's view,
' skip invidible columns
If cell.Visible Then
rc = New Rectangle(x, y, cell.Size.Width, cell.Size.Height)
e.Graphics.FillRectangle(Brushes.LightGray, rc)
e.Graphics.DrawRectangle(Pens.Black, rc)
' reused in the data pront - should be a function
Select Case DataGridView1.Columns(cell.ColumnIndex).DefaultCellStyle.Alignment
Case DataGridViewContentAlignment.BottomRight,
DataGridViewContentAlignment.MiddleRight
fmt.Alignment = StringAlignment.Far
rc.Offset(-1, 0)
Case DataGridViewContentAlignment.BottomCenter,
DataGridViewContentAlignment.MiddleCenter
fmt.Alignment = StringAlignment.Center
Case Else
fmt.Alignment = StringAlignment.Near
rc.Offset(2, 0)
End Select
e.Graphics.DrawString(DataGridView1.Columns(cell.ColumnIndex).HeaderText,
DataGridView1.Font, Brushes.Black, rc, fmt)
x += rc.Width
h = Math.Max(h, rc.Height)
End If
Next
y += h
End If
newpage = False
' now print the data for each row
Dim thisNDX As Int32
For thisNDX = mRow To DataGridView1.RowCount - 1
' no need to try to print the new row
If DataGridView1.Rows(thisNDX).IsNewRow Then Exit For
row = DataGridView1.Rows(thisNDX)
x = e.MarginBounds.Left
h = 0
' reset X for data
x = e.MarginBounds.Left
' print the data
For Each cell As DataGridViewCell In row.Cells
If cell.Visible Then
rc = New Rectangle(x, y, cell.Size.Width, cell.Size.Height)
' pick up any RowPrePaint rule
If Convert.ToString(row.Cells(2).Value.ToString) = "NG" Then
Using br As New SolidBrush(Color.MistyRose)
e.Graphics.FillRectangle(br, rc)
End Using
End If
e.Graphics.DrawRectangle(Pens.Black, rc)
Select Case DataGridView1.Columns(cell.ColumnIndex).DefaultCellStyle.Alignment
Case DataGridViewContentAlignment.BottomRight,
DataGridViewContentAlignment.MiddleRight
fmt.Alignment = StringAlignment.Far
rc.Offset(-1, 0)
Case DataGridViewContentAlignment.BottomCenter,
DataGridViewContentAlignment.MiddleCenter
fmt.Alignment = StringAlignment.Center
Case Else
fmt.Alignment = StringAlignment.Near
rc.Offset(2, 0)
End Select
e.Graphics.DrawString(cell.FormattedValue.ToString(),
DataGridView1.Font, Brushes.Black, rc, fmt)
x += rc.Width
h = Math.Max(h, rc.Height)
End If
Next
y += h
' next row to print
mRow = thisNDX + 1
If y + h > e.MarginBounds.Bottom Then
e.HasMorePages = True
mRow -= 1 'causes last row to rePrint on next page
newpage = True
Return
End If
Next
End Sub
Private Sub btnPrint_Click(sender As Object, e As EventArgs) Handles btnPrint.Click
'need to start fresh each time
mRow = 0
newpage = True
PrintPreviewDialog1.Document = PrintDocument1
'optionally reset the first page shown
PrintPreviewDialog1.PrintPreviewControl.StartPage = 0
PrintPreviewDialog1.WindowState = FormWindowState.Maximized
PrintPreviewDialog1.ShowDialog()
End Sub
Upvotes: 2
Views: 734
Reputation: 38875
Once the document has printed as a Preview, if you decide to print, the document has to be printed again. This means all that code in PrintDocument1_PrintPage
has to run again, this time sending the output to the printer.
However, at the end of the Preview, mRow
will be the max number of DGV rows and newpage
is false so it appears there is nothing to print. The solution is to initialize those in the BeginPrint
event:
Private Sub PrintDocument1_BeginPrint(sender As Object,
e As PrintEventArgs) Handles PrintDocument1.BeginPrint
mRow = 0
newpage = True
PrintPreviewDialog1.PrintPreviewControl.StartPage = 0
PrintPreviewDialog1.PrintPreviewControl.Zoom = 1.0
End Sub
Now, when printing starts again for the printer, they are set to process the entire document. The code also resets the first page to show and the initial Zoom.
Upvotes: 2