Cómo imprimir la tabla datagridview con su encabezado en vb.net?

Estoy creando una función de vista previa de impresión en un sistema que estoy desarrollando que hará una vista previa de la vista de cuadrícula de datos que quiero imprimir. Usé los códigos de Ooopsoft como referencia y funciona bien excepto por un pequeño problema.

Problema:

enter image description here

En el se puede ver que falta la fila dgv con el número de serie 1. Parece que el encabezado ha sobrescrito la primera fila. He intentado una infinidad de maneras de resolverlo, pero todavía no puedo encontrar la solución. Intenté salir del diálogo de vista previa de impresión y abrirlo de nuevo, pero este es el resultado que obtuve. Creo que me falta una línea de código, pero no puedo entender qué. Por favor ayuda.

El código original es un buen comienzo, pero tiene un par de errores e ineficiencias:

  • Utiliza el indicador de nueva página para imprimir el encabezado o la primera fila cuando hay una página nueva. Obviamente, realmente quieres que haga ambas cosas
  • La impresión de los encabezados de columna se realiza una vez por página, por lo que no necesita estar en el bucle de impresión de datos en absoluto
  • No permite columnas o columnas invisibles con una alineación distinta a la predeterminada. Puede haber otras configuraciones de este tipo que desee contabilizar.
  • Debido a que en realidad no está imprimiendo el número correcto de filas, una vez que lo arregle encontrará que reimprime la última fila de la página anterior como la primera fila de una página nueva.
  • Hay un margen interior o margen para que el texto no se imprima demasiado cerca de la cuadrícula; esto solo usa un desplazamiento de 1 o 2
  • También es innecesariamente usar single y RectangleF
  • Tampoco está preparado para que el Documento se muestre nuevamente o Impreso. También deseará restablecer mRow y newpage en el clic del botón o en el evento BeginPrint .

RowPrePaint algunos comentarios, así como colorear la fila del encabezado y demostrar cómo implementar cosas como una regla 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 here enter image description here

Tenga en cuenta que hay una columna Id configurada como invisible en el DGV, la columna Color está centrada y el Price está justificado a la izquierda; estas son todas las configuraciones recogidas del control. También tenga en cuenta que el texto se aleja de las líneas de la cuadrícula solo un poco.


El último punto anterior, también deseará restablecer mRow y newpage en el clic del botón o en el evento BeginPrint . significa esto:

 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 

Después de obtener una vista previa, la variable mRow indicará que se han impreso todas las filas. Si el usuario hace clic en Imprimir o vuelve para otra Vista previa, nada se imprimirá. Este código también restablece la primera página para mostrar y el Zoom inicial.