First row in DataGrid missing - vb.net

I'm trying to output a data grid that retrieves user data and puts it in a table. When I try to do this, I believe the first row is replaced by the column name, then an additional empty row gets added to the bottom. Can anyone see any discrepancies with this code chunk that may cause it to do this?
Data Input:
Output Given:
Here's my code:
Dim mRow As Integer = 0
Dim newpage As Boolean = True
With DataGridViewONE
Dim fmt As StringFormat = New StringFormat(StringFormatFlags.LineLimit)
fmt.LineAlignment = StringAlignment.Center
fmt.Trimming = StringTrimming.EllipsisCharacter
Dim y As Single = 770 'e.MarginBounds.Top
Do While mRow < .RowCount
Dim row As DataGridViewRow = .Rows(mRow)
Dim x As Single = e.MarginBounds.Left
Dim h As Single = 1
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 mRow = 0 Then
e.Graphics.DrawString(DataGridViewONE.Columns(cell.ColumnIndex).HeaderText,
.Font, Brushes.Black, rc, fmt)
Else
e.Graphics.DrawString(DataGridViewONE.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
EDIT
I have found that the ColumnIndex replaces the first row. Technically, if mRow was set to -1, there wouldn't be an issue, but doing so gives the error that index cannot be a negative value.
If mRow = 0 Then
e.Graphics.DrawString(DataGridViewONE.Columns(cell.ColumnIndex).HeaderText,
.Font, Brushes.Black, rc, fmt)
Replacing it with the Row DrawString would give the output I need but without the column headings

Related

How do I hide a column when printing a DataGridView?

I have in the last of all rows of a DataGridView a "remove" button. I want to not show the remove button when I print it. How can I do this? Also I need to not show the place of the remove button.
I tried setting the Visible property of the column to False, but that did not hide the column from the printout.
Me.DataGridView1.Columns("Remove").Visible = False
With DataGridView1
Using fmt As New StringFormat With {
.Alignment = StringAlignment.Center,
.LineAlignment = StringAlignment.Center,
.Trimming = StringTrimming.EllipsisCharacter,
.FormatFlags = StringFormatFlags.LineLimit Or StringFormatFlags.NoWrap
}
Dim y As Single = e.MarginBounds.Top
Using headerFont As New Font("Arial", 12, FontStyle.Bold)
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)
If newpage Then
e.Graphics.DrawString(DataGridView1.Columns(cell.ColumnIndex).HeaderText, headerFont, Brushes.Black, rc, fmt) '
Else
e.Graphics.DrawString(DataGridView1.Rows(cell.RowIndex).Cells(cell.ColumnIndex).FormattedValue.ToString(), headerFont, 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
End Using
End Using
mRow = 0
End With
If you find the index of the column you do not want to print, then you can check that index when iterating over the cells and simply skip over that iteration, something like this:
Me.DataGridView1.Columns("Remove").Visible = False
Dim skipRowNum = DataGridView1.Columns("Remove").Index
With DataGridView1
Using fmt As New StringFormat With {
.Alignment = StringAlignment.Center,
.LineAlignment = StringAlignment.Center,
.Trimming = StringTrimming.EllipsisCharacter,
.FormatFlags = StringFormatFlags.LineLimit Or StringFormatFlags.NoWrap
}
Dim y As Single = e.MarginBounds.Top
Using headerFont As New Font("Arial", 12, FontStyle.Bold)
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
If cell.ColumnIndex = skipRowNum Then
Continue For
End If
Dim rc As RectangleF = New RectangleF(x, y, cell.Size.Width, cell.Size.Height)
If newPage Then
e.Graphics.DrawString(DataGridView1.Columns(cell.ColumnIndex).HeaderText, headerFont, Brushes.Black, rc, fmt) '
Else
e.Graphics.DrawString(DataGridView1.Rows(cell.RowIndex).Cells(cell.ColumnIndex).FormattedValue.ToString(), headerFont, 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
End Using
End Using
mRow = 0
End With
You could easily extend that to exclude more than one column from being printed by using a List(Of Integer) for the columns to be skipped.
Dim skipRowNum = DataGridView1.Columns("Column1").Index
With DataGridView1
Using fmt As New StringFormat With {
.Alignment = StringAlignment.Center,
.LineAlignment = StringAlignment.Center,
.Trimming = StringTrimming.EllipsisCharacter,
.FormatFlags = StringFormatFlags.LineLimit Or StringFormatFlags.NoWrap
}
Dim y As Single = e.MarginBounds.Top
y = y + e.MarginBounds.Y + 30
Using headerFont As New Font("Arial", 12, FontStyle.Bold)
Do While mRow < .RowCount
Dim row As DataGridViewRow = .Rows(mRow)
Dim x As Single = e.MarginBounds.Left
Dim h As Single = 0
x = x + e.MarginBounds.X + 180
For Each cell As DataGridViewCell In row.Cells
If cell.ColumnIndex = skipRowNum Then
Continue For
End If
Dim rc As RectangleF = New RectangleF(x, y, cell.Size.Width, cell.Size.Height)
If newpage Then
e.Graphics.DrawString(DataGridView1.Columns(cell.ColumnIndex).HeaderText, headerFont, Brushes.Black, rc, fmt) '
Else
e.Graphics.DrawString(DataGridView1.Rows(cell.RowIndex).Cells(cell.ColumnIndex).FormattedValue.ToString(), headerFont, 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
End Using
End Using
mRow = 0
End With

How I Do DataGridView Print Text Alignment Center and Font Size Change VB.NET

I have use the below code it work fine but how i large the font size and how i center text alignment please help me this code worked just center and font size problem this code work but the problem is how i alignment between two row
With DataGridView1
Using fmt As New StringFormat With {
.Alignment = StringAlignment.Center,
.LineAlignment = StringAlignment.Center,
.Trimming = StringTrimming.EllipsisCharacter,
.FormatFlags = StringFormatFlags.LineLimit Or StringFormatFlags.NoWrap
}
Dim y As Single = e.MarginBounds.Top
Using headerFont As New Font("Arial", 14, FontStyle.Bold)
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)
If newpage Then
e.Graphics.DrawString(DataGridView1.Columns(cell.ColumnIndex).HeaderText, headerFont, Brushes.Black, rc, fmt) '
Else
e.Graphics.DrawString(DataGridView1.Rows(cell.RowIndex).Cells(cell.ColumnIndex).FormattedValue.ToString(), headerFont, 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
End Using
End Using
mRow = 0
End With

'Index was out of range. Must be non-negative and less than the size of the collection

I have a data grid view , I want to export to Excel.
I want to export only the Visible columns in the data grid view.
But I keep getting this error.
Private Sub btnExport_Click(sender As Object, e As EventArgs) Handles btnExport.Click
Dim ExcelApp As Excel.Application
Dim ExcelWorkBk As Excel.Workbook
Dim ExcelWorkSht As Excel.Worksheet
Dim i As Integer
Dim j As Integer
ExcelApp = New Excel.Application
ExcelWorkBk = ExcelApp.Workbooks.Add()
ExcelWorkSht = ExcelWorkBk.Sheets("Sheet1")
Dim columnsCount As Integer = DGVinfo3.Columns.Count
For i = 0 To DGVinfo3.RowCount - 1
If DGVinfo3.Columns(i).Visible = True Then
For j = 0 To DGVinfo3.ColumnCount - 1
For k As Integer = 0 To DGVinfo3.Columns.Count + 1
If DGVinfo3.Columns(k).Visible = True Then
ExcelWorkSht.Cells(1, k) = DGVinfo3.Columns(k - 1).HeaderText
ExcelWorkSht.Cells(1, k).Font.Bold = True
ExcelWorkSht.Cells(1, k).interior.color = RGB(192, 203, 219)
ExcelWorkSht.Cells(i + 1, j + 1) = DGVinfo3(j, i).Value
End If
Next
Next
End If
Next
End Sub
I keep getting this error:
System. Argument Out Of Range Exception: 'Index was out of range. Must be
non-negative and less than the size of the collection.'
Here is where I get the Error:
ExcelWorkSht.Cells(1, k) = DGVinfo3.Columns(k - 1).HeaderText
Just loop the rows and inside that loop each column. Also because the hidden columns won't be exported to Excel, it's probably best to keep track of the Excel columns in a separate variable:
Dim xlColumn As Integer
For i = 0 To DGVinfo3.RowCount - 1
xlColumn = 0
For j = 0 To DGVinfo3.ColumnCount - 1
If DGVinfo3.Columns(j).Visible = True Then
xlColumn += 1
If i = 0 Then
'You only need to set the column headers for the first row
ExcelWorkSht.Cells(1, xlColumn) = DGVinfo3.Columns(j).HeaderText
ExcelWorkSht.Cells(1, xlColumn).Font.Bold = True
ExcelWorkSht.Cells(1, xlColumn).interior.color = RGB(192, 203, 219)
End If
'i + 2 because the header is row 1
ExcelWorkSht.Cells(i + 2, xlColumn) = DGVinfo3(i, j).Value
End If
Next
Next

VB.net Printing text from a multiline textbox and several datagridviews after that

I am trying to print a multiline textbox and several different datagridviews after that. I hope some of the kind souls here would be able to help me.
So far, it works well when there is only one page from the datagridview, after that the last page of the text gets repeated.
Like so:
All Fine for Page 1
Problems afoot for every other page after that
To all who are about to read my code-mess, you have my utmost thanks.
Here's the code that I am using:
Dim mRow As Integer = 0
Dim newpage As Boolean = True
Dim page As Integer = 0
Dim tablepage As Integer = 0
Dim content1 As String
Dim numChars As Integer
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
PrintPreviewDialog1.Document = PrintDocument1
PrintPreviewDialog1.ShowDialog()
mRow = 0
newpage = True
page = 0
tablepage = 0
End Sub
Private Sub PrintDocument1_PrintPage(sender As Object, e As Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
Dim numLines As Integer
'1 Page
'TEXT
If page = 0 Then
content1 = TextBox6.Text & vbLf & TextBox7.Text & vbLf & TextBox8.Text
Dim stringForPage As String
Dim strFormat As New StringFormat()
Dim PrintFont As Font
PrintFont = TextBox6.Font
Dim rectDraw As New RectangleF(e.MarginBounds.Left, e.MarginBounds.Top, e.MarginBounds.Width, e.MarginBounds.Height)
Dim sizeMeasure As New SizeF(e.MarginBounds.Width, e.MarginBounds.Height - PrintFont.GetHeight(e.Graphics))
strFormat.Trimming = StringTrimming.Word
e.Graphics.MeasureString(content1, PrintFont, sizeMeasure, strFormat, numChars, numLines)
stringForPage = content1.Substring(0, numChars)
Dim rectDraw1 As New RectangleF(e.MarginBounds.Left, e.MarginBounds.Top, e.MarginBounds.Width, PrintFont.GetHeight(e.Graphics) * numLines)
e.Graphics.DrawString(stringForPage, PrintFont, Brushes.Black, rectDraw1, strFormat)
If numChars < content1.Length Then
content1 = content1.Substring(numChars)
e.HasMorePages = True
page += 1
Else
e.HasMorePages = False
'End If
'DATAGRIDVIEW
If tablepage > 0 Then
With TableDataGridView
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(TableDataGridView.Columns(cell.ColumnIndex).HeaderText, .Font, Brushes.Black, rc, fmt)
Else
e.Graphics.DrawString(TableDataGridView.Rows(cell.RowIndex - 1).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 ' 800 Then '
e.HasMorePages = True
newpage = True
mRow -= 1
Exit Sub
End If
Loop
End With
Else
'DATAGRIDVIEW < 2 page
With TableDataGridView
Dim fmt As StringFormat = New StringFormat(StringFormatFlags.LineLimit)
fmt.LineAlignment = StringAlignment.Center
fmt.Trimming = StringTrimming.EllipsisCharacter
Dim y As Single = 20 + rectDraw1.Bottom '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(TableDataGridView.Columns(cell.ColumnIndex).HeaderText, .Font, Brushes.Black, rc, fmt)
Else
e.Graphics.DrawString(TableDataGridView.Rows(cell.RowIndex - 1).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 '800 Then '
e.HasMorePages = True
newpage = True
mRow -= 1
tablepage += 1
Exit Sub
End If
Loop
End With
End If
End If
'TEXT
'More than 1 Page
ElseIf page > 0 Then
Dim stringForPage As String
Dim strFormat As New StringFormat()
Dim PrintFont As Font
PrintFont = TextBox6.Font
Dim rectDraw As New RectangleF(e.MarginBounds.Left, e.MarginBounds.Top, e.MarginBounds.Width, e.MarginBounds.Height)
Dim sizeMeasure As New SizeF(e.MarginBounds.Width, e.MarginBounds.Height - PrintFont.GetHeight(e.Graphics))
strFormat.Trimming = StringTrimming.Word
e.Graphics.MeasureString(content1, PrintFont, sizeMeasure, strFormat, numChars, numLines)
stringForPage = content1.Substring(0, numChars)
Dim rectDraw1 As New RectangleF(e.MarginBounds.Left, e.MarginBounds.Top, e.MarginBounds.Width, PrintFont.GetHeight(e.Graphics) * numLines)
e.Graphics.DrawString(stringForPage, PrintFont, Brushes.Black, rectDraw1, strFormat)
If numChars < content1.Length Then
content1 = content1.Substring(numChars)
e.HasMorePages = True
page += 1
Else
e.HasMorePages = False
'DATAGRIDVIEW
If tablepage > 0 Then
With TableDataGridView
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(TableDataGridView.Columns(cell.ColumnIndex).HeaderText, .Font, Brushes.Black, rc, fmt)
Else
e.Graphics.DrawString(TableDataGridView.Rows(cell.RowIndex - 1).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 ' 800 Then '
e.HasMorePages = True
newpage = True
mRow -= 1
Exit Sub
End If
Loop
End With
Else
'DATAGRIDVIEW < 2 page
With TableDataGridView
Dim fmt As StringFormat = New StringFormat(StringFormatFlags.LineLimit)
fmt.LineAlignment = StringAlignment.Center
fmt.Trimming = StringTrimming.EllipsisCharacter
Dim y As Single = 20 + rectDraw1.Bottom '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(TableDataGridView.Columns(cell.ColumnIndex).HeaderText, .Font, Brushes.Black, rc, fmt)
Else
e.Graphics.DrawString(TableDataGridView.Rows(cell.RowIndex - 1).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 '800 Then '
e.HasMorePages = True
newpage = True
mRow -= 1
tablepage += 1
Exit Sub
End If
Loop
End With
End If
End If
End If
End Sub
Instead of writing the same code over and over why not do something like
Static Pos AS Integer
For I = Pos To TableDataGridView.Rows.Count
'Do your graphics work here using TableDataGridView.Rows(i)
If y + h > e.MarginBounds.Bottom Then
Pos+=i
e.hasmorepages = true
Exit For
end if
next

Problems printing DataGridView

Hi I am using the following code to print a datagridview. It works but it prints every single column, even the ones that are not visible on the form. Is there a way to make it so it only prints visible columns. Thanks.
Private Structure pageDetails
Dim columns As Integer
Dim rows As Integer
Dim startCol As Integer
Dim startRow As Integer
End Structure
Private pages As Dictionary(Of Integer, pageDetails)
Dim maxPagesWide As Integer
Dim maxPagesTall As Integer
Private Sub PrintDocument1_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.BeginPrint
''this removes the printed page margins
PrintDocument1.OriginAtMargins = True
PrintDocument1.DefaultPageSettings.Margins = New Drawing.Printing.Margins(0, 0, 0, 0)
pages = New Dictionary(Of Integer, pageDetails)
Dim maxWidth As Integer = CInt(PrintDocument1.DefaultPageSettings.PrintableArea.Width) - 40
Dim maxHeight As Integer = CInt(PrintDocument1.DefaultPageSettings.PrintableArea.Height) - 40 + Label1.Height
Dim pageCounter As Integer = 0
pages.Add(pageCounter, New pageDetails)
Dim columnCounter As Integer = 0
Dim columnSum As Integer = DataGridView1.RowHeadersWidth
For c As Integer = 0 To DataGridView1.Columns.Count - 1
If columnSum + DataGridView1.Columns(c).Width < maxWidth Then
columnSum += DataGridView1.Columns(c).Width
columnCounter += 1
Else
pages(pageCounter) = New pageDetails With {.columns = columnCounter, .rows = 0, .startCol = pages(pageCounter).startCol}
columnSum = DataGridView1.RowHeadersWidth + DataGridView1.Columns(c).Width
columnCounter = 1
pageCounter += 1
pages.Add(pageCounter, New pageDetails With {.startCol = c})
End If
If c = DataGridView1.Columns.Count - 1 Then
If pages(pageCounter).columns = 0 Then
pages(pageCounter) = New pageDetails With {.columns = columnCounter, .rows = 0, .startCol = pages(pageCounter).startCol}
End If
End If
Next
maxPagesWide = pages.Keys.Max + 1
pageCounter = 0
Dim rowCounter As Integer = 0
Dim rowSum As Integer = DataGridView1.ColumnHeadersHeight
For r As Integer = 0 To DataGridView1.Rows.Count - 2
If rowSum + DataGridView1.Rows(r).Height < maxHeight Then
rowSum += DataGridView1.Rows(r).Height
rowCounter += 1
Else
pages(pageCounter) = New pageDetails With {.columns = pages(pageCounter).columns, .rows = rowCounter, .startCol = pages(pageCounter).startCol, .startRow = pages(pageCounter).startRow}
For x As Integer = 1 To maxPagesWide - 1
pages(pageCounter + x) = New pageDetails With {.columns = pages(pageCounter + x).columns, .rows = rowCounter, .startCol = pages(pageCounter + x).startCol, .startRow = pages(pageCounter).startRow}
Next
pageCounter += maxPagesWide
For x As Integer = 0 To maxPagesWide - 1
pages.Add(pageCounter + x, New pageDetails With {.columns = pages(x).columns, .rows = 0, .startCol = pages(x).startCol, .startRow = r})
Next
rowSum = DataGridView1.ColumnHeadersHeight + DataGridView1.Rows(r).Height
rowCounter = 1
End If
If r = DataGridView1.Rows.Count - 2 Then
For x As Integer = 0 To maxPagesWide - 1
If pages(pageCounter + x).rows = 0 Then
pages(pageCounter + x) = New pageDetails With {.columns = pages(pageCounter + x).columns, .rows = rowCounter, .startCol = pages(pageCounter + x).startCol, .startRow = pages(pageCounter + x).startRow}
End If
Next
End If
Next
maxPagesTall = pages.Count \ maxPagesWide
End Sub
Private Sub PrintDocument1_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
Dim rect As New Rectangle(20, 20, CInt(PrintDocument1.DefaultPageSettings.PrintableArea.Width), Label1.Height)
Dim sf As New StringFormat
sf.Alignment = StringAlignment.Center
sf.LineAlignment = StringAlignment.Center
e.Graphics.DrawString(Label1.Text, Label1.Font, Brushes.Black, rect, sf)
sf.Alignment = StringAlignment.Near
Dim startX As Integer = 50
Dim startY As Integer = rect.Bottom
Static startPage As Integer = 0
For p As Integer = startPage To pages.Count - 1
Dim cell As New Rectangle(startX, startY, DataGridView1.RowHeadersWidth, DataGridView1.ColumnHeadersHeight)
e.Graphics.FillRectangle(New SolidBrush(SystemColors.ControlLight), cell)
e.Graphics.DrawRectangle(Pens.Black, cell)
startY += DataGridView1.ColumnHeadersHeight
For r As Integer = pages(p).startRow To pages(p).startRow + pages(p).rows - 1
cell = New Rectangle(startX, startY, DataGridView1.RowHeadersWidth, DataGridView1.Rows(r).Height)
e.Graphics.FillRectangle(New SolidBrush(SystemColors.ControlLight), cell)
e.Graphics.DrawRectangle(Pens.Black, cell)
e.Graphics.DrawString(DataGridView1.Rows(r).HeaderCell.Value, DataGridView1.Font, Brushes.Black, cell, sf)
startY += DataGridView1.Rows(r).Height
Next
startX += cell.Width
startY = rect.Bottom
For c As Integer = pages(p).startCol To pages(p).startCol + pages(p).columns - 1
cell = New Rectangle(startX, startY, DataGridView1.Columns(c).Width, DataGridView1.ColumnHeadersHeight)
e.Graphics.FillRectangle(New SolidBrush(SystemColors.ControlLight), cell)
e.Graphics.DrawRectangle(Pens.Black, cell)
e.Graphics.DrawString(DataGridView1.Columns(c).HeaderCell.Value, DataGridView1.Font, Brushes.Black, cell, sf)
startX += DataGridView1.Columns(c).Width
Next
startY = rect.Bottom + DataGridView1.ColumnHeadersHeight
For r As Integer = pages(p).startRow To pages(p).startRow + pages(p).rows - 1
startX = 50 + DataGridView1.RowHeadersWidth
For c As Integer = pages(p).startCol To pages(p).startCol + pages(p).columns - 1
cell = New Rectangle(startX, startY, DataGridView1.Columns(c).Width, DataGridView1.Rows(r).Height)
e.Graphics.DrawRectangle(Pens.Black, cell)
e.Graphics.DrawString(DataGridView1(c, r).Value, DataGridView1.Font, Brushes.Black, cell, sf)
startX += DataGridView1.Columns(c).Width
Next
startY += DataGridView1.Rows(r).Height
Next
If p <> pages.Count - 1 Then
startPage = p + 1
e.HasMorePages = True
Return
Else
startPage = 0
End If
Next
End Sub
Private Sub PrintAMToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles PrintAMToolStripMenuItem.Click
PrintDocument1.DefaultPageSettings.Landscape = True
PrintDocument1.Print()
End Sub
I added If condition to your PrintDocument1_PrintPage and your PrintDocument1_BeginPrint events to check if the column is visible each time there is a loop against your columns:
Private Sub PrintDocument1_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.BeginPrint
''this removes the printed page margins
PrintDocument1.OriginAtMargins = True
PrintDocument1.DefaultPageSettings.Margins = New Drawing.Printing.Margins(0, 0, 0, 0)
pages = New Dictionary(Of Integer, pageDetails)
Dim maxWidth As Integer = CInt(PrintDocument1.DefaultPageSettings.PrintableArea.Width) - 40
Dim maxHeight As Integer = CInt(PrintDocument1.DefaultPageSettings.PrintableArea.Height) - 40 + Label1.Height
Dim pageCounter As Integer = 0
pages.Add(pageCounter, New pageDetails)
Dim columnCounter As Integer = 0
Dim columnSum As Integer = DataGridView1.RowHeadersWidth
For c As Integer = 0 To DataGridView1.Columns.Count - 1
If columnSum + DataGridView1.Columns(c).Width < maxWidth Then
columnSum += DataGridView1.Columns(c).Width
columnCounter += 1
Else
If DataGridView1.Columns(c).Visible = True Then
pages(pageCounter) = New pageDetails With {.columns = columnCounter, .rows = 0, .startCol = pages(pageCounter).startCol}
columnSum = DataGridView1.RowHeadersWidth + DataGridView1.Columns(c).Width
columnCounter = 1
pageCounter += 1
pages.Add(pageCounter, New pageDetails With {.startCol = c})
End If
End If
If c = DataGridView1.Columns.Count - 1 Then
If pages(pageCounter).columns = 0 Then
pages(pageCounter) = New pageDetails With {.columns = columnCounter, .rows = 0, .startCol = pages(pageCounter).startCol}
End If
End If
Next
maxPagesWide = pages.Keys.Max + 1
pageCounter = 0
Dim rowCounter As Integer = 0
Dim rowSum As Integer = DataGridView1.ColumnHeadersHeight
For r As Integer = 0 To DataGridView1.Rows.Count - 2
If rowSum + DataGridView1.Rows(r).Height < maxHeight Then
rowSum += DataGridView1.Rows(r).Height
rowCounter += 1
Else
pages(pageCounter) = New pageDetails With {.columns = pages(pageCounter).columns, .rows = rowCounter, .startCol = pages(pageCounter).startCol, .startRow = pages(pageCounter).startRow}
For x As Integer = 1 To maxPagesWide - 1
pages(pageCounter + x) = New pageDetails With {.columns = pages(pageCounter + x).columns, .rows = rowCounter, .startCol = pages(pageCounter + x).startCol, .startRow = pages(pageCounter).startRow}
Next
pageCounter += maxPagesWide
For x As Integer = 0 To maxPagesWide - 1
pages.Add(pageCounter + x, New pageDetails With {.columns = pages(x).columns, .rows = 0, .startCol = pages(x).startCol, .startRow = r})
Next
rowSum = DataGridView1.ColumnHeadersHeight + DataGridView1.Rows(r).Height
rowCounter = 1
End If
If r = DataGridView1.Rows.Count - 2 Then
For x As Integer = 0 To maxPagesWide - 1
If pages(pageCounter + x).rows = 0 Then
pages(pageCounter + x) = New pageDetails With {.columns = pages(pageCounter + x).columns, .rows = rowCounter, .startCol = pages(pageCounter + x).startCol, .startRow = pages(pageCounter + x).startRow}
End If
Next
End If
Next
maxPagesTall = pages.Count \ maxPagesWide
End Sub
Private Sub PrintDocument1_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
Dim rect As New Rectangle(20, 20, CInt(PrintDocument1.DefaultPageSettings.PrintableArea.Width), Label1.Height)
Dim sf As New StringFormat
sf.Alignment = StringAlignment.Center
sf.LineAlignment = StringAlignment.Center
e.Graphics.DrawString(Label1.Text, Label1.Font, Brushes.Black, rect, sf)
sf.Alignment = StringAlignment.Near
Dim startX As Integer = 50
Dim startY As Integer = rect.Bottom
Static startPage As Integer = 0
For p As Integer = startPage To pages.Count - 1
Dim cell As New Rectangle(startX, startY, DataGridView1.RowHeadersWidth, DataGridView1.ColumnHeadersHeight)
e.Graphics.FillRectangle(New SolidBrush(SystemColors.ControlLight), cell)
e.Graphics.DrawRectangle(Pens.Black, cell)
startY += DataGridView1.ColumnHeadersHeight
For r As Integer = pages(p).startRow To pages(p).startRow + pages(p).rows - 1
cell = New Rectangle(startX, startY, DataGridView1.RowHeadersWidth, DataGridView1.Rows(r).Height)
e.Graphics.FillRectangle(New SolidBrush(SystemColors.ControlLight), cell)
e.Graphics.DrawRectangle(Pens.Black, cell)
e.Graphics.DrawString(DataGridView1.Rows(r).HeaderCell.Value, DataGridView1.Font, Brushes.Black, cell, sf)
startY += DataGridView1.Rows(r).Height
Next
startX += cell.Width
startY = rect.Bottom
For c As Integer = pages(p).startCol To pages(p).startCol + pages(p).columns - 1
If DataGridView1.Columns(c).Visible = True Then
cell = New Rectangle(startX, startY, DataGridView1.Columns(c).Width, DataGridView1.ColumnHeadersHeight)
e.Graphics.FillRectangle(New SolidBrush(SystemColors.ControlLight), cell)
e.Graphics.DrawRectangle(Pens.Black, cell)
e.Graphics.DrawString(DataGridView1.Columns(c).HeaderCell.Value, DataGridView1.Font, Brushes.Black, cell, sf)
startX += DataGridView1.Columns(c).Width
End If
Next
startY = rect.Bottom + DataGridView1.ColumnHeadersHeight
For r As Integer = pages(p).startRow To pages(p).startRow + pages(p).rows - 1
startX = 50 + DataGridView1.RowHeadersWidth
For c As Integer = pages(p).startCol To pages(p).startCol + pages(p).columns - 1
If DataGridView1.Columns(c).Visible = True Then
cell = New Rectangle(startX, startY, DataGridView1.Columns(c).Width, DataGridView1.Rows(r).Height)
e.Graphics.DrawRectangle(Pens.Black, cell)
e.Graphics.DrawString(DataGridView1(c, r).Value, DataGridView1.Font, Brushes.Black, cell, sf)
startX += DataGridView1.Columns(c).Width
End If
Next
startY += DataGridView1.Rows(r).Height
Next
If p <> pages.Count - 1 Then
startPage = p + 1
e.HasMorePages = True
Return
Else
startPage = 0
End If
Next
End Sub