the code below was actually copied from one of the stackoverflow answers, it's not showing the first row in print preview. Its skipping the first row and shwing starting from second.
here's the code,
Dim mRow As Integer = 0
Dim newpage As Boolean = True
Private Sub PrintDocument1_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
newpage = True
With dgvData
Dim fmt As StringFormat = New StringFormat(StringFormatFlags.LineLimit)
'Dim fmt2 As StringFormat = New StringFormat(StringFormatFlags.LineLimit)
fmt.LineAlignment = StringAlignment.Center
'Dim font As Font
'font = New Font("Microsoft Sans Serif", "13", FontStyle.Underline, GraphicsUnit.Inch, gdiCharSet:=1)
'fmt.Trimming = StringTrimming.EllipsisCharacter
Dim rc1 As RectangleF = New RectangleF(460, 20, 350, 20)
Dim rc2 As RectangleF = New RectangleF(500, 40, 350, 20)
e.Graphics.DrawString("Some Heading", .Font, Brushes.Black, rc1, fmt)
e.Graphics.DrawString("Another heading ", .Font, Brushes.Black, rc2, fmt)
Dim y As Single = e.MarginBounds.Top + 60
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(dgvData.Columns(cell.ColumnIndex).HeaderText.ToString, .Font, Brushes.Black, rc, fmt)
'MessageBox.Show(dgvData.Columns(cell.ColumnIndex).HeaderText.ToString)
Else
e.Graphics.DrawString(dgvData.Rows(cell.RowIndex).Cells(cell.ColumnIndex).FormattedValue.ToString(), .Font, Brushes.Black, rc, fmt)
'MessageBox.Show(dgvData.Rows(cell.RowIndex).ToString)
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
[If I'm understanding this correctly,] It skips the first line because newpage
is set to True, so when you get to this code:
If (newpage) Then
e.Graphics.DrawString(dgvData.Columns(cell.ColumnIndex).HeaderText.ToString, .Font, Brushes.Black, rc, fmt)
'MessageBox.Show(dgvData.Columns(cell.ColumnIndex).HeaderText.ToString)
Else
e.Graphics.DrawString(dgvData.Rows(cell.RowIndex).Cells(cell.ColumnIndex).FormattedValue.ToString(), .Font, Brushes.Black, rc, fmt)
'MessageBox.Show(dgvData.Rows(cell.RowIndex).ToString)
End If
you are printing a header, instead of the cell in the current line (Dim row As DataGridViewRow = .Rows(mRow)
).
Edit in response to "So should I set the newage = false at start, or is there anything else I should do?"
If newpage
evaluates to True, you need to output BOTH the header and the current line. In the original code you are using an If
switch to do one or the other (thus skipping output of the current line). I did some quick reorganizing, and below is my new suggested code in its entirety, so you can compare.
Dim mRow As Integer = 0
Dim newpage As Boolean = True
Private Sub PrintDocument1_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
newpage = True
With dgvData
Dim fmt As StringFormat = New StringFormat(StringFormatFlags.LineLimit)
'Dim fmt2 As StringFormat = New StringFormat(StringFormatFlags.LineLimit)
fmt.LineAlignment = StringAlignment.Center
'Dim font As Font
'font = New Font("Microsoft Sans Serif", "13", FontStyle.Underline, GraphicsUnit.Inch, gdiCharSet:=1)
'fmt.Trimming = StringTrimming.EllipsisCharacter
Dim rc1 As RectangleF = New RectangleF(460, 20, 350, 20)
Dim rc2 As RectangleF = New RectangleF(500, 40, 350, 20)
e.Graphics.DrawString("Some Heading", .Font, Brushes.Black, rc1, fmt)
e.Graphics.DrawString("Another heading ", .Font, Brushes.Black, rc2, fmt)
Dim rc As RectangleF
Dim y As Single = e.MarginBounds.Top + 60
Do While mRow < .RowCount
Dim row As DataGridViewRow = .Rows(mRow)
Dim x As Single = e.MarginBounds.Left
Dim h As Single = 0
If (newpage) Then
For Each cell As DataGridViewCell In row.Cells
rc = New RectangleF(x, y, cell.Size.Width, cell.Size.Height)
e.Graphics.DrawRectangle(Pens.Black, rc.Left, rc.Top, rc.Width, rc.Height)
e.Graphics.DrawString(dgvData.Columns(cell.ColumnIndex).HeaderText.ToString, .Font, Brushes.Black, rc, fmt)
'MessageBox.Show(dgvData.Columns(cell.ColumnIndex).HeaderText.ToString)
x += rc.Width
h = Math.Max(h, rc.Height)
Next
newpage = False
y += h
x = e.MarginBounds.Left
h = 0
End If
For Each cell As DataGridViewCell In row.Cells
rc = New RectangleF(x, y, cell.Size.Width, cell.Size.Height)
e.Graphics.DrawRectangle(Pens.Black, rc.Left, rc.Top, rc.Width, rc.Height)
e.Graphics.DrawString(dgvData.Rows(cell.RowIndex).Cells(cell.ColumnIndex).FormattedValue.ToString(), .Font, Brushes.Black, rc, fmt)
'MessageBox.Show(dgvData.Rows(cell.RowIndex).ToString)
x += rc.Width
h = Math.Max(h, rc.Height)
Next
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
Some of the changes to note:
newpage
switch is segregated from the For Each
that outputs the actual cells. This causes the current row to be output regardless of the newpage
condition.x
, h
, and y
) have to be incremented or modified both inside the switch as well as outside, so those lines are now duplicated.rc
was moved outside the Do While
loop. There's no need to declare it for every cell; instead just assign a new value.y + h > e.MarginBounds.Bottom
more than once (unless you're printing REALLY BIG), as you can assume that you're only ever printing more than one line if you're already at the top of a new page, so it stays by itself at the end of the loop.Math.Max(h, rc.Height)
, h
is always zero or equal to rc.Height, so you might consider rethinking this.