如何在 vb.net 中打印带有标题的 datagridview 表?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41015287/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 20:08:00  来源:igfitidea点击:

How to print datagridview table with its header in vb.net?

.netvb.netdatagridviewprintdocument

提问by Lucynda

I'm creating a print preview function in a system that I'm developing which will preview the datagridview that I want to print. I used ooopsoft's codesas reference and it works fine except for a slight problem.

我正在我正在开发的系统中创建一个打印预览功能,该功能将预览我想要打印的数据网格视图。我使用 ooopsoft 的代码作为参考,除了一个小问题外,它工作正常。

Problem:

问题:

enter image description here

在此处输入图片说明

In the you can see that the dgv row with serial number 1 is missing. It appears the header has overwritten the 1st row. I have tried a myriad of ways to solve it, but I still can't find the solution. I tried exiting the print preview dialog and opening it again, but thisis the result I got. I think I'm missing a line of code, but I can't figure out what. Please help.

在您可以看到序列号为 1 的 dgv 行丢失。看起来标题已经覆盖了第一行。我尝试了无数方法来解决它,但我仍然找不到解决方案。我试图退出打印预览对话框,然后再次打开它,不过是结果我得到了。我想我错过了一行代码,但我不知道是什么。请帮忙。

回答by ??ssa P?ngj?rdenlarp

The original codeis a nice start but has a couple of bugs and inefficiecies:

原代码是一个很好的开始,但有几个bug和inefficiecies的:

  • It uses the newpageflag to print the header orthe first row when there is a new page. Obviously you really want it to do both
  • Printing the column headers is done once per page, so it doesnt need to be in the data print loop at all
  • It is not allowing for invisible columns or columns with other than default alignment, There could be other such settings you want to account for.
  • Because it is not actually printing the correct number of rows, once you fix that you'll find that it reprints the last row from the previous page as the first row of a new page.
  • There is an internal gutter or margin so that text does not print too close to gridlines - this just uses an offset of 1 or 2
  • It is also needlessly using singleand RectangleF
  • It is also not prepared for the Document to be shown again or Printed. You will also want to reset mRowand newpageeither in the button click or BeginPrintevent.
  • 当有新页面时,它使用该newpage标志来打印页眉第一行。显然你真的希望它同时做
  • 每页打印列标题一次,因此根本不需要在数据打印循环中
  • 它不允许不可见的列或非默认对齐的列,您可能需要考虑其他此类设置。
  • 因为它实际上并没有打印正确的行数,所以一旦您修复它,您会发现它将上一页的最后一行重新打印为新页面的第一行。
  • 有一个内部装订线或边距,因此文本不会打印得太靠近网格线 - 这仅使用 1 或 2 的偏移量
  • 它也不必要地使用singleRectangleF
  • 它也不准备再次显示或打印文档。您还需要在按钮单击或事件中重置mRow和。newpageBeginPrint

I added a few comments as well as coloring the header row and demonstrating how to implement things like a RowPrePaintrule.

我添加了一些注释,并为标题行着色并演示了如何实现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

enter image description hereenter image description here

在此处输入图片说明在此处输入图片说明

Note that there is an Idcolumn set to invisible in the DGV, the Colorcolumn is centered and Priceis left justified - these are all settings picked up from the control. Also note that the text is moved away from the gridlines just a bit.

请注意,Id在 DGV中有一个设置为不可见的Color列,该列居中并Price左对齐 - 这些都是从控件中选取的设置。另请注意,文本稍微远离网格线。



The last bullet point above, You will also want to reset mRowand newpageeither in the button click or BeginPrintevent.means this:

上述最后一颗子弹点,你也将要重置mRow,并newpage在按一下按钮或任一BeginPrint事件。这意味着:

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

After you preview the mRowvariable will indicate that all the rows have been printed. If the user clicks Print or goes back for another Preview, nothing will print. This code also resets the first page to show and the initial Zoom.

预览后,mRow变量将指示所有行都已打印。如果用户单击打印或返回另一个预览,则不会打印任何内容。此代码还会重置要显示的第一页和初始缩放。