skip to Main Content

I have created a print preview for the data grid view that I want to print. The code works fine but there is slight problem

Problem Screenshot:Print screenshot

In the data grid view row, the ID 1 is missing, it always starts from 2. How can I solve this problem? Please help.

My code:

 Private Sub PrintDocument1_PrintPage(sender As System.Object, e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage

    Dim mRow As Integer = 0
    Dim newpage As Boolean = True
    PrintDocument1.DefaultPageSettings.Landscape = True

    With DataGridView1
        Dim fmt As StringFormat = New StringFormat(StringFormatFlags.LineLimit)
        fmt.LineAlignment = StringAlignment.Center
        fmt.Trimming = StringTrimming.EllipsisCharacter
        Dim y As Single = e.MarginBounds.Top
        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(DataGridView1.Columns(cell.ColumnIndex).HeaderText, .Font, Brushes.Black, rc, fmt)
                Else
                    e.Graphics.DrawString(DataGridView1.Rows(cell.RowIndex).Cells(cell.ColumnIndex).FormattedValue.ToString(), .Font, Brushes.Black, rc, fmt)
                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

3

Answers


  1. The If (newpage) causes it to draw the headers instead of the first row.

    You could change the section

    newpage = False
    y += h
    mRow += 1
    

    to

    If not newpage Then
        mRow += 1
    End If
    newpage = False
    y += h
    
    Login or Signup to reply.
  2. rows(0) is the first data row, not header row, while cell.RowIndex is 1, so change rows(cell.RowIndex) as rows(cell.RowIndex-1) :

    e.Graphics.DrawString(DataGridView1.Rows(cell.RowIndex - 1).Cells(cell.ColumnIndex).FormattedValue.ToString(), .Font, Brushes.Black, rc, fmt) 
    
    Login or Signup to reply.
  3. Print each part separately to avoid this kind of problems. The headers part belongs to the Columns collection then print it first before you handle the Rows and Cells parts.

    You have another problem in your code to fix. The mRow is a local variable that does not preserve the last printed row to skip or the new row to continue with when you request a new page. It must be a class field.

    Private mRow As Integer
    
    Private Sub PrintPreviewButton(sender As Object, e As EventArgs) _
        Handles Button1.Click
        PrintDocument1.DefaultPageSettings.Landscape = True
        mRow = 0
    
        Using d = New PrintPreviewDialog With {
            .Document = PrintDocument1
        }
            d.ShowDialog(Me)
        End Using
    End Sub
    
    Private Sub PrintDocument1_PrintPage(sender As Object, e As PrintPageEventArgs) _
        Handles PrintDocument1.PrintPage
        Dim g = e.Graphics
        Dim x As Integer = e.MarginBounds.X
        Dim y As Integer = e.MarginBounds.Y
    
        With DataGridView1
            Using sf = New StringFormat(StringFormat.GenericTypographic) With {
            .LineAlignment = StringAlignment.Center,
            .Trimming = StringTrimming.EllipsisCharacter
            }
                For Each col As DataGridViewColumn In .Columns
                    Dim rect = New Rectangle(
                        x, y,
                        col.Width, col.DataGridView.ColumnHeadersHeight)
    
                    g.DrawRectangle(Pens.Black, rect)
                    rect.Inflate(-3, 0)
                    g.DrawString(col.HeaderText, .Font, Brushes.Black, rect, sf)
    
                    x += col.Width
                Next
    
                y += .ColumnHeadersHeight
    
                For i = mRow To .RowCount - 1
                    Dim row = .Rows(i)
    
                    If row.IsNewRow Then Exit Sub
    
                    x = e.MarginBounds.X
    
                    For Each cell As DataGridViewCell In row.Cells
                        Dim rect = New Rectangle(New Point(x, y), cell.Size)
    
                        g.DrawRectangle(Pens.Black, rect)
                        rect.Inflate(-3, 0)
                        g.DrawString(cell.FormattedValue?.ToString(),
                                        .Font, Brushes.Black, rect, sf)
    
                        x += cell.Size.Width
                    Next cell
    
                    y += row.Height
    
                    If y + row.Height > e.MarginBounds.Bottom Then
                        mRow = i + 1
                        e.HasMorePages = True
                        Exit For
                    End If
                Next i
            End Using
        End With
    End Sub
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search