简体   繁体   English

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

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

I'm creating a print preview function in a system that I'm developing which will preview the datagridview that I want to print. 我正在开发的系统中创建打印预览功能,该功能将预览我要打印的datagridview。 I used ooopsoft's codes as reference and it works fine except for a slight problem. 我使用了ooopsoft的代码作为参考,除了有一个小问题外,它工作正常。

Problem: 问题:

在此处输入图片说明

In the you can see that the dgv row with serial number 1 is missing. 在中,您会看到序列号为1的dgv行丢失了。 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 this is the result I got. 我试图退出打印预览对话框,然后再次打开它,不过是结果我得到了。 I think I'm missing a line of code, but I can't figure out what. 我想我缺少一行代码,但是我不知道是什么。 Please help. 请帮忙。

The original code is a nice start but has a couple of bugs and inefficiecies: 原始代码是一个不错的开始,但是存在一些错误和低效率:

  • It uses the newpage flag to print the header or the first row when there is a new page. 当有新页面时,它使用newpage标志打印标题第一行。 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 有一个内部装订线或页边距,因此文本不会打印得离网格线太近-这仅使用1或2的偏移量
  • It is also needlessly using single and RectangleF 也不必要使用singleRectangleF
  • It is also not prepared for the Document to be shown again or Printed. 还没有准备好再次显示或打印文档。 You will also want to reset mRow and newpage either in the button click or BeginPrint event. 你也将要重置mRownewpage无论是在点击按钮或BeginPrint事件。

I added a few comments as well as coloring the header row and demonstrating how to implement things like a RowPrePaint rule. 我添加了一些注释,以及为标题行着色并演示了如何实现类似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

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

Note that there is an Id column set to invisible in the DGV, the Color column is centered and Price is left justified - these are all settings picked up from the control. 请注意,在DGV中有一个Id列设置为不可见,在Color列居中,并且Price左对齐-这些都是从控件中选取的设置。 Also note that the text is moved away from the gridlines just a bit. 还要注意,文本只是稍微偏离了网格线。


The last bullet point above, You will also want to reset mRow and newpage either in the button click or BeginPrint event. 上述最后一颗子弹点, 你也将要重置mRownewpage在点击按钮或任BeginPrint事件。 means this: 意味着:

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 mRow variable will indicate that all the rows have been printed. 预览后, mRow变量将指示所有行均已打印。 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. 此代码还重置要显示的第一页和初始“缩放”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM