vb.net 在 PrintDocument 中打印 DataGridView

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22580715/
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 17:11:14  来源:igfitidea点击:

Printing DataGridView in PrintDocument

vb.net

提问by user3450006

I am a new to vb.net, I with my team are developing a system where we dominantly use DataGridView in viewing our records from SQL Server database.

我是 vb.net 的新手,我和我的团队正在开发一个系统,我们主要使用 DataGridView 查看来自 SQL Server 数据库的记录。

Here's my problem, i have two DataGridViews where one extracts the ID and Student name while the other one extracts records(grades of the student) based on the other DataGridView row selected. I can already print the records but when i close the PrintDocument(without exiting the form) and choose another student and view it again in PrintDocument,

这是我的问题,我有两个 DataGridView,其中一个提取 ID 和学生姓名,而另一个根据所选的另一个 DataGridView 行提取记录(学生的成绩)。我已经可以打印记录,但是当我关闭 PrintDocument(不退出表单)并选择另一个学生并在 PrintDocument 中再次查看时,

it gives me an error saying

它给了我一个错误说

"Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index"

"Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index"

and a follow-up problem occurs, when i have this code "cell.RowIndex - 1", the first record in the DatagridView can't be printed in the PrintDocument and when i erase the "- 1" in the code, the header goes crazy, sometimes they go blank(w/ borders) and sometimes they really do not display, only the records are displayed.

并且出现后续问题,当我有此代码时"cell.RowIndex - 1",无法在 PrintDocument 中打印 DatagridView 中的第一条记录,并且当我删除代码中的“-1”时,标题会变得疯狂,有时它们会变成空白(带边框)有时它们真的不显示,只显示记录。

this is where the error occurs:

这是发生错误的地方:

 e.Graphics.DrawString(DataGridView1.Rows(cell.RowIndex - 1) 
    .Cells(cell.ColumnIndex).FormattedValue.ToString, .Font, 
     Brushes.Black, rc, frmt)

This is my code:

这是我的代码:

Private Sub PrintDocument1_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
    With DataGridView1
        Dim frmt As StringFormat = New StringFormat(StringFormatFlags.LineLimit)
        frmt.LineAlignment = StringAlignment.Center
        frmt.Trimming = StringTrimming.EllipsisCharacter

        Dim HeaderFont As Font = New Drawing.Font("Times New Roman", 20)
        Dim reportFont As Font = New Drawing.Font("Times New Roman", 14)
        Dim nrmlfnt As Font = New Drawing.Font("Calbiri", 10)
        Dim drawBrush As New SolidBrush(Color.Black)
        Dim blackpen As New Pen(Color.Black, 1)

        e.Graphics.DrawString("First Fruits Christian Academy", HeaderFont, drawBrush, 250, 50)
        e.Graphics.DrawString("Purok 17 Hindangon, Valencia City Bukidnon", reportFont, drawBrush, 245, 80)
        e.Graphics.DrawString("Student Grade", reportFont, drawBrush, 370, 125)
        e.Graphics.DrawString("Name: " & txtName.Text & "", nrmlfnt, drawBrush, 100, 180)
        e.Graphics.DrawString("Gender: " & txtGender.Text & "", nrmlfnt, drawBrush, 600, 180)
        e.Graphics.DrawString("Grade & Section: " & cboYearLevel.Text & " - " & cboSection.Text & "", nrmlfnt, drawBrush, 100, 200)

        Dim y As Single = e.MarginBounds.Top + 125
        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 - 20, cell.Size.Height)
                e.Graphics.DrawRectangle(Pens.Black, rc.Left, rc.Top, rc.Width, rc.Height)
                    If (newpage) Then
                        e.Graphics.DrawString(DataGridView1.Columns(cell.ColumnIndex).HeaderText, .Font, Brushes.Black, rc, frmt)
                    Else
                    e.Graphics.DrawString(DataGridView1.Rows(cell.RowIndex - 1).Cells(cell.ColumnIndex).FormattedValue.ToString, .Font, Brushes.Black, rc, frmt)
                    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
                newpage = True
                Exit Sub
            End If
        Loop
        mRow = 0
    End With
End Sub

回答by OneFineDay

The best way to print things from a DataGridViewis to make a collection of each row into a List(Of String)making use of String.Formatto concatenate the values together. Use a class variable for where in the list you are at for the next pages to continue.

从 a 打印事物的最佳方法DataGridView是将每一行的集合组合成一个List(Of String)用于String.Format将值连接在一起的用途。使用类变量表示您在列表中的位置,以便下一页继续。

Private index As Integer
Private Sub Print(...) Handles PrintDocument1.PrintPage
   Dim row As Integer = {some point you want to start at}
  'Paint a title - since this event fires for each page
  'continue loop or start loop
  For i As Integer = index To myList.Count - 1
   If Not row = e.MarginBounds.Bottom - 12 Then
    'remember where we are in the list
    index = i
    'paint your contents
   Else
    'start new page
    e.HasMorePages = True
    Exit Sub
   End If
  Next
  'reset the index for next print job
  If Not e.HasMorePages Then index = 0 
 End Sub

Dim myList As New List (Of String)
For Each row In dgv.Rows
  'add what data you want to print
Next

回答by sallushan

Probably you need to remove the Elsepart from this code,

可能您需要Else从此代码中删除该部分,

If (newpage) Then
    e.Graphics.DrawString(DataGridView1.Columns(cell.ColumnIndex).HeaderText, .Font, Brushes.Black, rc, frmt)
Else
    e.Graphics.DrawString(DataGridView1.Rows(cell.RowIndex - 1).Cells(cell.ColumnIndex).FormattedValue.ToString, .Font, Brushes.Black, rc, frmt)
End If

And change it to,

并将其更改为,

If (newpage) Then
    e.Graphics.DrawString(DataGridView1.Columns(cell.ColumnIndex).HeaderText, .Font, Brushes.Black, rc, frmt)
End If
' and at this point you should re-calculate your rectangle again
e.Graphics.DrawString(DataGridView1.Rows(cell.RowIndex - 1).Cells(cell.ColumnIndex).FormattedValue.ToString, .Font, Brushes.Black, rc, frmt)

The point is, on each iteration, you have to print the row, so if the newpage flag is true then it means you just need to print the header first before you print the line.

关键是,在每次迭代中,您必须打印 row,因此如果 newpage 标志为真,则意味着您只需要在打印行之前先打印标题即可。

回答by pablo

me and prove your code worked, now the problem is that servers provide last row of data. I made changes to make it work are:

我并证明您的代码有效,现在问题是服务器提供最后一行数据。我进行了更改以使其正常工作:

Dim NewPage As Boolean 
? NewPage = True 

? If (NewPage) = True Then 
????e.Graphics.DrawString (FDesempe?o.DataGridView1.Columns (cell.ColumnIndex) .HeaderText, .font, Brushes.Black, rc, frmt) 
?
else 
??e.Graphics.DrawString (FDesempe?o.DataGridView1.Rows (cell.RowIndex - 1) .Cells (cell.ColumnIndex) .FormattedValue.ToString, .font, Brushes.Black, rc, frmt) 
End If 

I hope you found served, by the way I am newbie like you. if you can correct the error if I agradesericia you can contact us by email, my email is [email protected]

我希望你能找到服务,顺便说一下,我和你一样是新手。如果您可以更正错误,如果我是 agradesericia 您可以通过电子邮件与我们联系,我的电子邮件是 [email protected]