这段代码有什么问题?它没有在 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 条件如何。
  • 一些变量(xhy)必须在开关内部和外部递增或修改,因此这些行现在是重复的。
  • rc 的声明被移到 Do While 循环之外。无需为每个单元格声明它;而只是分配一个新值。
  • 确实没有必要多次检查 y + h > e.MarginBounds.Bottom(除非您打印的非常大),因为如果您已经在新页面的顶部,因此它在循环结束时保持独立。
  • 当您评估 Math.Max(h, rc.Height) 时,h 始终为零或等于 rc.Height,因此您可能会考虑重新考虑这一点。