如何打印 datagridview table 及其在 vb.net 中的 header?
How to print datagridview table with its header in vb.net?
我正在开发的系统中创建打印预览功能,该功能将预览我要打印的 datagridview。我使用 ooopsoft 的 codes 作为参考,除了一个小问题外,它工作正常。
问题:
您可以看到缺少序列号为 1 的 dgv 行。 header 似乎覆盖了第一行。我已经尝试了无数种方法来解决它,但我仍然找不到解决方案。我尝试退出打印预览对话框并再次打开它,但 this 是我得到的结果。我想我错过了一行代码,但我不知道是什么。请帮忙。
original code 是一个不错的开始,但有一些错误和低效:
- 它使用
newpage
标志在有新页面时打印header或第一行。显然你真的希望它能同时做到这两点
- 每页打印一次列 headers,因此根本不需要在数据打印循环中
- 不允许不可见的列或非默认对齐方式的列,您可能需要考虑其他此类设置。
- 因为它实际上并没有打印正确的行数,所以一旦您解决了这个问题,您会发现它会将上一页的最后一行重新打印为新页面的第一行。
- 有内部装订线或边距,这样文本打印时不会太靠近网格线 - 这仅使用 1 或 2 的偏移量
- 也无谓地使用了
single
和RectangleF
- 也不准备再次显示或打印文档。您还需要在按钮单击或
BeginPrint
事件中重置 mRow
和 newpage
。
我添加了一些评论并为 header 行着色并演示了如何实施 RowPrePaint
规则之类的东西。
Private mRow As Integer = 0
Private newpage As Boolean = True
Private Sub PrintDocument1_PrintPage(sender As System.Object,
e As PrintPageEventArgs) Handles PrintDocument1.PrintPage
' 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 = dgvZZ.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 dgvZZ.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(dgvZZ.Columns(cell.ColumnIndex).HeaderText,
dgvZZ.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 dgvZZ.RowCount - 1
' no need to try to print the new row
If dgvZZ.Rows(thisNDX).IsNewRow Then Exit For
row = dgvZZ.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)
' SAMPLE CODE: How To
' up a RowPrePaint rule
'If Convert.ToDecimal(row.Cells(5).Value) < 9.99 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 dgvZZ.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(),
dgvZZ.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
请注意,在 DGV 中有一个 Id
列设置为不可见,Color
列居中,Price
左对齐 - 这些都是从控制。另请注意,文本稍微偏离了网格线。
上面的最后一个要点,您还需要在按钮单击或 BeginPrint
事件中重置 mRow
和 newpage
。 意思是:
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
预览后,mRow
变量将指示所有行都已打印。如果用户单击打印或返回另一个预览,则不会打印任何内容。此代码还重置要显示的第一页和初始缩放。
我正在开发的系统中创建打印预览功能,该功能将预览我要打印的 datagridview。我使用 ooopsoft 的 codes 作为参考,除了一个小问题外,它工作正常。
问题:
您可以看到缺少序列号为 1 的 dgv 行。 header 似乎覆盖了第一行。我已经尝试了无数种方法来解决它,但我仍然找不到解决方案。我尝试退出打印预览对话框并再次打开它,但 this 是我得到的结果。我想我错过了一行代码,但我不知道是什么。请帮忙。
original code 是一个不错的开始,但有一些错误和低效:
- 它使用
newpage
标志在有新页面时打印header或第一行。显然你真的希望它能同时做到这两点 - 每页打印一次列 headers,因此根本不需要在数据打印循环中
- 不允许不可见的列或非默认对齐方式的列,您可能需要考虑其他此类设置。
- 因为它实际上并没有打印正确的行数,所以一旦您解决了这个问题,您会发现它会将上一页的最后一行重新打印为新页面的第一行。
- 有内部装订线或边距,这样文本打印时不会太靠近网格线 - 这仅使用 1 或 2 的偏移量
- 也无谓地使用了
single
和RectangleF
- 也不准备再次显示或打印文档。您还需要在按钮单击或
BeginPrint
事件中重置mRow
和newpage
。
我添加了一些评论并为 header 行着色并演示了如何实施 RowPrePaint
规则之类的东西。
Private mRow As Integer = 0
Private newpage As Boolean = True
Private Sub PrintDocument1_PrintPage(sender As System.Object,
e As PrintPageEventArgs) Handles PrintDocument1.PrintPage
' 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 = dgvZZ.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 dgvZZ.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(dgvZZ.Columns(cell.ColumnIndex).HeaderText,
dgvZZ.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 dgvZZ.RowCount - 1
' no need to try to print the new row
If dgvZZ.Rows(thisNDX).IsNewRow Then Exit For
row = dgvZZ.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)
' SAMPLE CODE: How To
' up a RowPrePaint rule
'If Convert.ToDecimal(row.Cells(5).Value) < 9.99 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 dgvZZ.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(),
dgvZZ.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
请注意,在 DGV 中有一个 Id
列设置为不可见,Color
列居中,Price
左对齐 - 这些都是从控制。另请注意,文本稍微偏离了网格线。
上面的最后一个要点,您还需要在按钮单击或 BeginPrint
事件中重置 mRow
和 newpage
。 意思是:
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
预览后,mRow
变量将指示所有行都已打印。如果用户单击打印或返回另一个预览,则不会打印任何内容。此代码还重置要显示的第一页和初始缩放。