这段代码有什么问题?它没有在 PrintPreview 中显示第一行
What's wrong with this code? it's not showing the first row in PrintPreview
下面的代码实际上是从一个 Whosebug 答案中复制的,它没有在打印预览中显示第一行。它跳过第一行并从第二行开始显示。
这是代码,
Dim mRow As Integer = 0
Dim newpage As Boolean = True
Private Sub PrintDocument1_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
newpage = True
With dgvData
Dim fmt As StringFormat = New StringFormat(StringFormatFlags.LineLimit)
'Dim fmt2 As StringFormat = New StringFormat(StringFormatFlags.LineLimit)
fmt.LineAlignment = StringAlignment.Center
'Dim font As Font
'font = New Font("Microsoft Sans Serif", "13", FontStyle.Underline, GraphicsUnit.Inch, gdiCharSet:=1)
'fmt.Trimming = StringTrimming.EllipsisCharacter
Dim rc1 As RectangleF = New RectangleF(460, 20, 350, 20)
Dim rc2 As RectangleF = New RectangleF(500, 40, 350, 20)
e.Graphics.DrawString("Some Heading", .Font, Brushes.Black, rc1, fmt)
e.Graphics.DrawString("Another heading ", .Font, Brushes.Black, rc2, fmt)
Dim y As Single = e.MarginBounds.Top + 60
Do While mRow < .RowCount
Dim row As DataGridViewRow = .Rows(mRow)
Dim x As Single = e.MarginBounds.Left
Dim h As Single = 0
For Each cell As DataGridViewCell In row.Cells
Dim rc As RectangleF = New RectangleF(x, y, cell.Size.Width, cell.Size.Height)
e.Graphics.DrawRectangle(Pens.Black, rc.Left, rc.Top, rc.Width, rc.Height)
If (newpage) Then
e.Graphics.DrawString(dgvData.Columns(cell.ColumnIndex).HeaderText.ToString, .Font, Brushes.Black, rc, fmt)
'MessageBox.Show(dgvData.Columns(cell.ColumnIndex).HeaderText.ToString)
Else
e.Graphics.DrawString(dgvData.Rows(cell.RowIndex).Cells(cell.ColumnIndex).FormattedValue.ToString(), .Font, Brushes.Black, rc, fmt)
'MessageBox.Show(dgvData.Rows(cell.RowIndex).ToString)
End If
x += rc.Width
h = Math.Max(h, rc.Height)
Next
newpage = False
y += h
mRow += 1
If y + h > e.MarginBounds.Bottom Then
e.HasMorePages = True
mRow -= 1
newpage = True
Exit Sub
End If
Loop
mRow = 0
End With
End Sub
[如果我理解正确,] 它会跳过第一行,因为 newpage
设置为 True,所以当你看到这段代码时:
If (newpage) Then
e.Graphics.DrawString(dgvData.Columns(cell.ColumnIndex).HeaderText.ToString, .Font, Brushes.Black, rc, fmt)
'MessageBox.Show(dgvData.Columns(cell.ColumnIndex).HeaderText.ToString)
Else
e.Graphics.DrawString(dgvData.Rows(cell.RowIndex).Cells(cell.ColumnIndex).FormattedValue.ToString(), .Font, Brushes.Black, rc, fmt)
'MessageBox.Show(dgvData.Rows(cell.RowIndex).ToString)
End If
您正在打印 header,而不是当前行 (Dim row As DataGridViewRow = .Rows(mRow)
) 中的单元格。
编辑 以响应“那么我应该在开始时设置 newage = false 吗,或者还有什么我应该做的吗? “
如果 newpage
计算结果为 True,您需要同时输出 header 和当前行。在原始代码中,您使用 If
开关来做一个或另一个(因此跳过当前行的输出)。我做了一些快速的重组,下面是我的新建议的完整代码,所以你可以比较。
Dim mRow As Integer = 0
Dim newpage As Boolean = True
Private Sub PrintDocument1_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
newpage = True
With dgvData
Dim fmt As StringFormat = New StringFormat(StringFormatFlags.LineLimit)
'Dim fmt2 As StringFormat = New StringFormat(StringFormatFlags.LineLimit)
fmt.LineAlignment = StringAlignment.Center
'Dim font As Font
'font = New Font("Microsoft Sans Serif", "13", FontStyle.Underline, GraphicsUnit.Inch, gdiCharSet:=1)
'fmt.Trimming = StringTrimming.EllipsisCharacter
Dim rc1 As RectangleF = New RectangleF(460, 20, 350, 20)
Dim rc2 As RectangleF = New RectangleF(500, 40, 350, 20)
e.Graphics.DrawString("Some Heading", .Font, Brushes.Black, rc1, fmt)
e.Graphics.DrawString("Another heading ", .Font, Brushes.Black, rc2, fmt)
Dim rc As RectangleF
Dim y As Single = e.MarginBounds.Top + 60
Do While mRow < .RowCount
Dim row As DataGridViewRow = .Rows(mRow)
Dim x As Single = e.MarginBounds.Left
Dim h As Single = 0
If (newpage) Then
For Each cell As DataGridViewCell In row.Cells
rc = New RectangleF(x, y, cell.Size.Width, cell.Size.Height)
e.Graphics.DrawRectangle(Pens.Black, rc.Left, rc.Top, rc.Width, rc.Height)
e.Graphics.DrawString(dgvData.Columns(cell.ColumnIndex).HeaderText.ToString, .Font, Brushes.Black, rc, fmt)
'MessageBox.Show(dgvData.Columns(cell.ColumnIndex).HeaderText.ToString)
x += rc.Width
h = Math.Max(h, rc.Height)
Next
newpage = False
y += h
x = e.MarginBounds.Left
h = 0
End If
For Each cell As DataGridViewCell In row.Cells
rc = New RectangleF(x, y, cell.Size.Width, cell.Size.Height)
e.Graphics.DrawRectangle(Pens.Black, rc.Left, rc.Top, rc.Width, rc.Height)
e.Graphics.DrawString(dgvData.Rows(cell.RowIndex).Cells(cell.ColumnIndex).FormattedValue.ToString(), .Font, Brushes.Black, rc, fmt)
'MessageBox.Show(dgvData.Rows(cell.RowIndex).ToString)
x += rc.Width
h = Math.Max(h, rc.Height)
Next
y += h
mRow += 1
If y + h > e.MarginBounds.Bottom Then
e.HasMorePages = True
mRow -= 1
newpage = True
Exit Sub
End If
Loop
mRow = 0
End With
End Sub
需要注意的一些变化:
newpage
开关与输出实际单元格的 For Each
分开。这会导致输出当前行,而不管 newpage
条件如何。
- 一些变量(
x
、h
和 y
)必须在开关内部和外部递增或修改,因此这些行现在是重复的。
rc
的声明被移到 Do While
循环之外。无需为每个单元格声明它;而只是分配一个新值。
- 确实没有必要多次检查
y + h > e.MarginBounds.Bottom
(除非您打印的非常大),因为如果您已经在新页面的顶部,因此它在循环结束时保持独立。
- 当您评估
Math.Max(h, rc.Height)
时,h
始终为零或等于 rc.Height,因此您可能会考虑重新考虑这一点。
下面的代码实际上是从一个 Whosebug 答案中复制的,它没有在打印预览中显示第一行。它跳过第一行并从第二行开始显示。
这是代码,
Dim mRow As Integer = 0
Dim newpage As Boolean = True
Private Sub PrintDocument1_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
newpage = True
With dgvData
Dim fmt As StringFormat = New StringFormat(StringFormatFlags.LineLimit)
'Dim fmt2 As StringFormat = New StringFormat(StringFormatFlags.LineLimit)
fmt.LineAlignment = StringAlignment.Center
'Dim font As Font
'font = New Font("Microsoft Sans Serif", "13", FontStyle.Underline, GraphicsUnit.Inch, gdiCharSet:=1)
'fmt.Trimming = StringTrimming.EllipsisCharacter
Dim rc1 As RectangleF = New RectangleF(460, 20, 350, 20)
Dim rc2 As RectangleF = New RectangleF(500, 40, 350, 20)
e.Graphics.DrawString("Some Heading", .Font, Brushes.Black, rc1, fmt)
e.Graphics.DrawString("Another heading ", .Font, Brushes.Black, rc2, fmt)
Dim y As Single = e.MarginBounds.Top + 60
Do While mRow < .RowCount
Dim row As DataGridViewRow = .Rows(mRow)
Dim x As Single = e.MarginBounds.Left
Dim h As Single = 0
For Each cell As DataGridViewCell In row.Cells
Dim rc As RectangleF = New RectangleF(x, y, cell.Size.Width, cell.Size.Height)
e.Graphics.DrawRectangle(Pens.Black, rc.Left, rc.Top, rc.Width, rc.Height)
If (newpage) Then
e.Graphics.DrawString(dgvData.Columns(cell.ColumnIndex).HeaderText.ToString, .Font, Brushes.Black, rc, fmt)
'MessageBox.Show(dgvData.Columns(cell.ColumnIndex).HeaderText.ToString)
Else
e.Graphics.DrawString(dgvData.Rows(cell.RowIndex).Cells(cell.ColumnIndex).FormattedValue.ToString(), .Font, Brushes.Black, rc, fmt)
'MessageBox.Show(dgvData.Rows(cell.RowIndex).ToString)
End If
x += rc.Width
h = Math.Max(h, rc.Height)
Next
newpage = False
y += h
mRow += 1
If y + h > e.MarginBounds.Bottom Then
e.HasMorePages = True
mRow -= 1
newpage = True
Exit Sub
End If
Loop
mRow = 0
End With
End Sub
[如果我理解正确,] 它会跳过第一行,因为 newpage
设置为 True,所以当你看到这段代码时:
If (newpage) Then
e.Graphics.DrawString(dgvData.Columns(cell.ColumnIndex).HeaderText.ToString, .Font, Brushes.Black, rc, fmt)
'MessageBox.Show(dgvData.Columns(cell.ColumnIndex).HeaderText.ToString)
Else
e.Graphics.DrawString(dgvData.Rows(cell.RowIndex).Cells(cell.ColumnIndex).FormattedValue.ToString(), .Font, Brushes.Black, rc, fmt)
'MessageBox.Show(dgvData.Rows(cell.RowIndex).ToString)
End If
您正在打印 header,而不是当前行 (Dim row As DataGridViewRow = .Rows(mRow)
) 中的单元格。
编辑 以响应“那么我应该在开始时设置 newage = false 吗,或者还有什么我应该做的吗? “
如果 newpage
计算结果为 True,您需要同时输出 header 和当前行。在原始代码中,您使用 If
开关来做一个或另一个(因此跳过当前行的输出)。我做了一些快速的重组,下面是我的新建议的完整代码,所以你可以比较。
Dim mRow As Integer = 0
Dim newpage As Boolean = True
Private Sub PrintDocument1_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
newpage = True
With dgvData
Dim fmt As StringFormat = New StringFormat(StringFormatFlags.LineLimit)
'Dim fmt2 As StringFormat = New StringFormat(StringFormatFlags.LineLimit)
fmt.LineAlignment = StringAlignment.Center
'Dim font As Font
'font = New Font("Microsoft Sans Serif", "13", FontStyle.Underline, GraphicsUnit.Inch, gdiCharSet:=1)
'fmt.Trimming = StringTrimming.EllipsisCharacter
Dim rc1 As RectangleF = New RectangleF(460, 20, 350, 20)
Dim rc2 As RectangleF = New RectangleF(500, 40, 350, 20)
e.Graphics.DrawString("Some Heading", .Font, Brushes.Black, rc1, fmt)
e.Graphics.DrawString("Another heading ", .Font, Brushes.Black, rc2, fmt)
Dim rc As RectangleF
Dim y As Single = e.MarginBounds.Top + 60
Do While mRow < .RowCount
Dim row As DataGridViewRow = .Rows(mRow)
Dim x As Single = e.MarginBounds.Left
Dim h As Single = 0
If (newpage) Then
For Each cell As DataGridViewCell In row.Cells
rc = New RectangleF(x, y, cell.Size.Width, cell.Size.Height)
e.Graphics.DrawRectangle(Pens.Black, rc.Left, rc.Top, rc.Width, rc.Height)
e.Graphics.DrawString(dgvData.Columns(cell.ColumnIndex).HeaderText.ToString, .Font, Brushes.Black, rc, fmt)
'MessageBox.Show(dgvData.Columns(cell.ColumnIndex).HeaderText.ToString)
x += rc.Width
h = Math.Max(h, rc.Height)
Next
newpage = False
y += h
x = e.MarginBounds.Left
h = 0
End If
For Each cell As DataGridViewCell In row.Cells
rc = New RectangleF(x, y, cell.Size.Width, cell.Size.Height)
e.Graphics.DrawRectangle(Pens.Black, rc.Left, rc.Top, rc.Width, rc.Height)
e.Graphics.DrawString(dgvData.Rows(cell.RowIndex).Cells(cell.ColumnIndex).FormattedValue.ToString(), .Font, Brushes.Black, rc, fmt)
'MessageBox.Show(dgvData.Rows(cell.RowIndex).ToString)
x += rc.Width
h = Math.Max(h, rc.Height)
Next
y += h
mRow += 1
If y + h > e.MarginBounds.Bottom Then
e.HasMorePages = True
mRow -= 1
newpage = True
Exit Sub
End If
Loop
mRow = 0
End With
End Sub
需要注意的一些变化:
newpage
开关与输出实际单元格的For Each
分开。这会导致输出当前行,而不管newpage
条件如何。- 一些变量(
x
、h
和y
)必须在开关内部和外部递增或修改,因此这些行现在是重复的。 rc
的声明被移到Do While
循环之外。无需为每个单元格声明它;而只是分配一个新值。- 确实没有必要多次检查
y + h > e.MarginBounds.Bottom
(除非您打印的非常大),因为如果您已经在新页面的顶部,因此它在循环结束时保持独立。 - 当您评估
Math.Max(h, rc.Height)
时,h
始终为零或等于 rc.Height,因此您可能会考虑重新考虑这一点。