Understanding Datagridview Printing - vb.net

hello guys i just need help in understanding this block of code.
this code is a datagridview printing code that i want to edit to suit my needs but i dont know where to start i tried searching youtube tutorial but i cant seem to find any that explain this(printdocument control). so i want to make the margin a little narrow and to change font for column header and records. i tried changing default/properities of the datagridview and exploring a bit changing all numbers i see in the block of code but i cant seem to understand how it works. and if possible i also want to add a header where i can put a logo.
Private Sub pd_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles pd.PrintPage
Try
Dim actualWidth As Integer = dgvInventoryLog.Columns.Cast(Of DataGridViewColumn).Sum(Function(c) c.Width)
Dim percentage As Decimal = CDec(((100 / actualWidth) * e.MarginBounds.Width) / 100)
Dim header As String = "Inventory Log"
Dim footer As String
Dim startX As Integer = e.MarginBounds.Left
Dim startY As Integer = e.MarginBounds.Top
Dim r As Rectangle
Dim headerFont As New Font(dgvInventoryLog.Font.FontFamily, 15, FontStyle.Italic, GraphicsUnit.Pixel)
Dim szf As SizeF = e.Graphics.MeasureString(header, headerFont)
e.Graphics.DrawString(header, headerFont, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - szf.Width) / 2, startY - szf.Height)
footer = "Page " & pageCounter.ToString
szf = e.Graphics.MeasureString(footer, headerFont)
e.Graphics.DrawString(footer, headerFont, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - szf.Width) / 2, e.MarginBounds.Bottom + 5)
startY += 5
'this is the text alignment
Dim sf As New StringFormat
sf.Alignment = StringAlignment.Center
sf.LineAlignment = StringAlignment.Center
Dim gridFont As New Font(dgvInventoryLog.Font.FontFamily, dgvInventoryLog.Font.Size, FontStyle.Regular, GraphicsUnit.Pixel)
' If startRow = 0 Then
For x As Integer = 0 To dgvInventoryLog.Columns.Count - 1
r.X = startX
r.Y = startY
r.Width = CInt(dgvInventoryLog.Columns(x).Width * percentage)
r.Height = dgvInventoryLog.Rows(0).Height
e.Graphics.DrawRectangle(Pens.Black, r)
e.Graphics.DrawString(dgvInventoryLog.Columns(x).HeaderText, gridFont, Brushes.Black, r, sf)
startX += r.Width
Next
startY += r.Height
' End If
For y As Integer = startRow To dgvInventoryLog.Rows.Count - 1
If y = dgvInventoryLog.NewRowIndex Then Continue For
startX = e.MarginBounds.Left
For x As Integer = 0 To dgvInventoryLog.Columns.Count - 1
r.X = startX
r.Y = startY
r.Width = CInt(dgvInventoryLog.Columns(x).Width * percentage)
r.Height = dgvInventoryLog.Rows(0).Height
e.Graphics.DrawRectangle(Pens.Black, r)
' e.Graphics.DrawString(If(Not dgvInventoryLog.Rows(y).Cells(x).FormattedValue Is Nothing, dgvInventoryLog.Rows(y).Cells(x).Value.ToString, ""),
'gridFont, Brushes.Black, r, sf)
If x = 6 Then
Dim movementDate As Date = CType(dgvInventoryLog.Rows(y).Cells(x).Value, Date)
e.Graphics.DrawString(movementDate.ToString("dd/MM/yyyy"),
gridFont, Brushes.Black, r, sf)
' or dd/MM/yyyy
Else
e.Graphics.DrawString(If(Not dgvInventoryLog.Rows(y).Cells(x).Value Is Nothing, dgvInventoryLog.Rows(y).Cells(x).Value.ToString, ""),
gridFont, Brushes.Black, r, sf)
End If
startX += r.Width
Next
startY += r.Height
If startY >= e.MarginBounds.Bottom - 10 Then
If y < dgvInventoryLog.Rows.Count - 1 Then
e.HasMorePages = True
pageCounter += 1
startRow = y + 1
Exit For
End If
End If
Next
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
this is the output
ps: im not that experience in stackoverflow(im always just copying code here and there) so if this is not where i should post question like this i will be grateful if you can direct me to the proper place.

Related

How to remove the time in my Date column when printing

i have a program that print a datagridview and have a date column in it.
the column display date only but when i try to print it, it will have time add how can i remove it?
this is how it looks in the datagridview
and this is my printpreview
print code
Try
dgvInventoryLog.Columns(6).DefaultCellStyle.Format = "dd/MM/yyyy"
Dim actualWidth As Integer = dgvInventoryLog.Columns.Cast(Of DataGridViewColumn).Sum(Function(c) c.Width)
Dim percentage As Decimal = CDec(((100 / actualWidth) * e.MarginBounds.Width) / 100)
Dim header As String = "Inventory Log"
Dim footer As String
Dim startX As Integer = e.MarginBounds.Left
Dim startY As Integer = e.MarginBounds.Top
Dim r As Rectangle
Dim headerFont As New Font(dgvInventoryLog.Font.FontFamily, 15, FontStyle.Italic, GraphicsUnit.Pixel)
Dim szf As SizeF = e.Graphics.MeasureString(header, headerFont)
e.Graphics.DrawString(header, headerFont, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - szf.Width) / 2, startY - szf.Height)
footer = "Page " & pageCounter.ToString
szf = e.Graphics.MeasureString(footer, headerFont)
e.Graphics.DrawString(footer, headerFont, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - szf.Width) / 2, e.MarginBounds.Bottom + 5)
startY += 5
'this is the text alignment
Dim sf As New StringFormat
sf.Alignment = StringAlignment.Center
sf.LineAlignment = StringAlignment.Center
Dim gridFont As New Font(dgvInventoryLog.Font.FontFamily, dgvInventoryLog.Font.Size, FontStyle.Regular, GraphicsUnit.Pixel)
' If startRow = 0 Then
For x As Integer = 0 To dgvInventoryLog.Columns.Count - 1
r.X = startX
r.Y = startY
r.Width = CInt(dgvInventoryLog.Columns(x).Width * percentage)
r.Height = dgvInventoryLog.Rows(0).Height
e.Graphics.DrawRectangle(Pens.Black, r)
e.Graphics.DrawString(dgvInventoryLog.Columns(x).HeaderText, gridFont, Brushes.Black, r, sf)
startX += r.Width
Next
startY += r.Height
' End If
For y As Integer = startRow To dgvInventoryLog.Rows.Count - 1
If y = dgvInventoryLog.NewRowIndex Then Continue For
startX = e.MarginBounds.Left
For x As Integer = 0 To dgvInventoryLog.Columns.Count - 1
r.X = startX
r.Y = startY
r.Width = CInt(dgvInventoryLog.Columns(x).Width * percentage)
r.Height = dgvInventoryLog.Rows(0).Height
e.Graphics.DrawRectangle(Pens.Black, r)
e.Graphics.DrawString(If(Not dgvInventoryLog.Rows(y).Cells(x).Value Is Nothing, dgvInventoryLog.Rows(y).Cells(x).Value.ToString, ""),
gridFont, Brushes.Black, r, sf)
startX += r.Width
Next
startY += r.Height
If startY >= e.MarginBounds.Bottom - 10 Then
If y < dgvInventoryLog.Rows.Count - 1 Then
e.HasMorePages = True
pageCounter += 1
startRow = y + 1
Exit For
End If
End If
Next
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
Private Sub btnPrint_Click(sender As Object, e As EventArgs) Handles btnPrint.Click
''preview button
pageCounter = 1
startRow = 0
ppd.Document = pd
ppd.WindowState = FormWindowState.Maximized
ppd.ShowDialog()
End Sub
Private Sub getInventoryLog()
Using conn As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\INVENTORY_DB.accdb")
Dim cmd As New OleDbCommand("Select ItemCode as [ITEM CODE], ItemName AS [ITEM NAME], Description AS [DESCRIPTION], Price AS [PRICE],
Unit AS [UNIT], Quantity AS [QUANTITY], MovementDate AS [MOVEMENT DATE], `From` AS [FROM],
`To` AS [TO] From [Items Movement]", conn)
Dim da As New OleDbDataAdapter
Dim dt As New DataTable
da.SelectCommand = cmd
dt.Clear()
da.Fill(dt)
dgvInventoryLog.Columns.Clear()
dgvInventoryLog.DataSource = dt
dgvInventoryLog.Columns(0).Width = 80
dgvInventoryLog.Columns(1).Width = 250
dgvInventoryLog.Columns(2).Width = 150
dgvInventoryLog.Columns(3).Width = 70
dgvInventoryLog.Columns(4).Width = 70
dgvInventoryLog.Columns(5).Width = 100
dgvInventoryLog.Columns(6).Width = 110
dgvInventoryLog.Columns(7).Width = 135
dgvInventoryLog.Columns(8).Width = 135
End Using
End Sub
this is where i get the code for printing. i dont quite understand it, but its working just fine so i just copy paste it, so if that is where i messed up i will be grateful for pointing it out for me. thanks
https://www.vbforums.com/showthread.php?872037-RESOLVED-Need-help-with-printing-datagridview-content
Inside your loop, check if it's the 7th column (index 6), then convert the value to date and format it as you wish
For x As Integer = 0 To dgvInventoryLog.Columns.Count - 1
r.X = startX
r.Y = startY
r.Width = CInt(dgvInventoryLog.Columns(x).Width * percentage)
r.Height = dgvInventoryLog.Rows(0).Height
e.Graphics.DrawRectangle(Pens.Black, r)
If x = 6 Then
Dim movementDate As Date = Ctype(dgvInventoryLog.Rows(y).Cells(x).Value, Date)
e.Graphics.DrawString(movementDate.ToString("MM/dd/yyyy"),
gridFont, Brushes.Black, r, sf)
' or dd/MM/yyyy
Else
e.Graphics.DrawString(If(Not dgvInventoryLog.Rows(y).Cells(x).Value Is Nothing, dgvInventoryLog.Rows(y).Cells(x).Value.ToString, ""),
gridFont, Brushes.Black, r, sf)
End If
startX += r.Width
Next
You can make it so that the printing code respects the formatting in all columns, regardless of data type.
Dim value = dgvInventoryLog.Rows(y).Cells(x).Value
Dim format = dgvInventoryLog.Columns(x).DefaultCellStyle.Format
Dim text = If(String.IsNullOrEmpty(format),
value.ToString(),
String.Format($"{{0:{format}}}", value))
e.Graphics.DrawString(text, gridFont, Brushes.Black, r, sf)
That will work for any type and any legitimate format and it will also work with empty cells, whether they contain Nothing or DBNull.Value. What gets printed will be the same as what is displayed in the grid regardless.
This bit:
String.Format($"{{0:{format}}}", value)
might look a bit weird, so let me explain. The $ indicates string interpolation. Anything wrapped in braces within that interpolated string is evaluated and replaced with the result, with literal braces escaped with another brace. If, for instance, format contained "dd/MM/yyyy", $"{{0:{format}}}" would produce "{0:dd/MM/yyyy}". When that gets passed to String.Format, it is replaced with the contents of value in the specified format.
EDIT:
Note that, if you prefer, this:
Dim text = If(String.IsNullOrEmpty(format),
value.ToString(),
String.Format($"{{0:{format}}}", value))
could be replaced with this:
Dim text = String.Format(If(String.IsNullOrEmpty(format),
"{0}",
$"{{0:{format}}}"),
value)

Display only date in datagridview while printing

I'm building an attendance management project in vb.net. It will filter data of students between two dates and show the attendance. I'm using ms access 2007 database. When I display date from my database to datagridview column it is showing date only which is what I want but when I'm printing the gridview it shows date along with 00:00:00 which is not right. Please help me with this. My professor wants it and he himself doesnt know how to solve.
I'm adding complete code here:
Imports System.Data.OleDb
Public Class completeattendace
Dim con As New OleDbConnection("Provider = Microsoft.ACE.OLEDB.12.0;Data Source = C:\User\AMS\Attendance.accdb")
Dim pageCounter As Integer
Dim startRow As Integer
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
con.Open()
If ComboBox1.SelectedItem = "1BCASE01" Then
Dim cmd As New OleDbCommand("Select stud_roll, stud_name, course_code, attend_date, status From Course1 Where attend_date between #" & DateTimePicker1.Value.Date & "# and #" & DateTimePicker2.Value.Date & "# order by attend_date asc", con)
Dim da As New OleDbDataAdapter
da.SelectCommand = cmd
Dim dt As New DataTable
dt.Clear()
da.Fill(dt)
DataGridView1.DataSource = dt
con.Close()
End If
If ComboBox1.SelectedItem = "SKNKJAD" Then
Dim cmd As New OleDbCommand("Select stud_roll, stud_name, course_code, attend_date, status From Course2 Where attend_date between #" & DateTimePicker1.Value.Date & "# and #" & DateTimePicker2.Value.Date & "# order by attend_date asc", con)
Dim da As New OleDbDataAdapter
da.SelectCommand = cmd
Dim dt As New DataTable
dt.Clear()
da.Fill(dt)
DataGridView1.DataSource = dt
con.Close()
End If
If ComboBox1.SelectedItem = "MSNDAD" Then
Dim cmd As New OleDbCommand("Select stud_roll, stud_name, course_code, attend_date, status From Course3 Where attend_date between #" & DateTimePicker1.Value.Date & "# and #" & DateTimePicker2.Value.Date & "# order by attend_date asc", con)
Dim da As New OleDbDataAdapter
da.SelectCommand = cmd
Dim dt As New DataTable
dt.Clear()
da.Fill(dt)
DataGridView1.DataSource = dt
con.Close()
End If
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
pageCounter = 1
startRow = 0
PrintPreviewDialog1.Document = PrintDocument1
PrintPreviewDialog1.WindowState = FormWindowState.Maximized
PrintPreviewDialog1.ShowDialog()
End Sub
Private Sub PrintDocument1_PrintPage(sender As Object, e As Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
Dim actualWidth As Integer = DataGridView1.Columns.Cast(Of DataGridViewColumn).Sum(Function(c) c.Width)
Dim percentage As Decimal = ((100 / actualWidth) * e.MarginBounds.Width) / 100
Dim college As String = "College"
Dim header As String = "Attendance Report"
Dim course As String = "Course Code:-" + ComboBox1.SelectedItem
Dim dateattend As String = "Date :-" + DateTimePicker1.Value.Date + " - " + DateTimePicker2.Value.Date
Dim footer As String
Dim startX As Integer = e.MarginBounds.Left
Dim startY As Integer = e.MarginBounds.Top
Dim r As Rectangle
Dim collegeFont As New Font(DataGridView1.Font.FontFamily, 35, FontStyle.Bold, GraphicsUnit.Pixel)
Dim szf As SizeF = e.Graphics.MeasureString(college, collegeFont)
e.Graphics.DrawString(college, collegeFont, Brushes.Red, e.MarginBounds.Left + (e.MarginBounds.Width - szf.Width) / 2, startY - szf.Height - 40)
Dim headerFont As New Font(DataGridView1.Font.FontFamily, 25, FontStyle.Bold, GraphicsUnit.Pixel)
szf = e.Graphics.MeasureString(header, headerFont)
e.Graphics.DrawString(header, headerFont, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - szf.Width) / 2, startY - szf.Height)
Dim courseFont As New Font(DataGridView1.Font.FontFamily, 15, FontStyle.Bold, GraphicsUnit.Pixel)
szf = e.Graphics.MeasureString(course, courseFont)
e.Graphics.DrawString(course, courseFont, Brushes.Black, e.MarginBounds.Left, startY - szf.Height + 40)
Dim datefont As New Font(DataGridView1.Font.FontFamily, 15, FontStyle.Bold, GraphicsUnit.Pixel)
szf = e.Graphics.MeasureString(dateattend, datefont)
e.Graphics.DrawString(dateattend, datefont, Brushes.Black, e.MarginBounds.Left, startY - szf.Height + 70)
footer = "Page " & pageCounter.ToString
Dim footerFont As New Font(DataGridView1.Font.FontFamily, 10, FontStyle.Regular, GraphicsUnit.Pixel)
szf = e.Graphics.MeasureString(footer, footerFont)
e.Graphics.DrawString(footer, footerFont, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - szf.Width) / 2, e.MarginBounds.Bottom + 5)
startY += 100
'this is the text alignment
Dim sf As New StringFormat
sf.Alignment = StringAlignment.Center
sf.LineAlignment = StringAlignment.Center
Dim gridFont As New Font(DataGridView1.Font.FontFamily, 12 * percentage, FontStyle.Regular, GraphicsUnit.Pixel)
If startRow = 0 Then
For x As Integer = 0 To DataGridView1.Columns.Count - 1
r.X = startX
r.Y = startY
r.Width = DataGridView1.Columns(x).Width * percentage
r.Height = DataGridView1.Rows(0).Height
e.Graphics.DrawRectangle(Pens.Black, r)
e.Graphics.DrawString(DataGridView1.Columns(x).HeaderText, gridFont, Brushes.Black, r, sf)
startX += r.Width
Next
startY += r.Height
End If
For y As Integer = startRow To DataGridView1.Rows.Count - 1
If y = DataGridView1.NewRowIndex Then Continue For
startX = e.MarginBounds.Left
For x As Integer = 0 To DataGridView1.Columns.Count - 1
r.X = startX
r.Y = startY
r.Width = DataGridView1.Columns(x).Width * percentage
r.Height = DataGridView1.Rows(0).Height
e.Graphics.DrawRectangle(Pens.Black, r)
e.Graphics.DrawString(If(Not DataGridView1.Rows(y).Cells(x).Value Is Nothing, DataGridView1.Rows(y).Cells(x).Value.ToString, ""),
gridFont, Brushes.Black, r, sf)
startX += r.Width
Next
startY += r.Height
If startY >= e.MarginBounds.Bottom - 10 Then
If y < DataGridView1.Rows.Count - 1 Then
e.HasMorePages = True
pageCounter += 1
startRow = y + 1
Exit For
End If
End If
Next
End Sub
End Class
You have two options. The simple option is to change:
e.Graphics.DrawString(If(Not DataGridView1.Rows(y).Cells(x).Value Is Nothing, DataGridView1.Rows(y).Cells(x).Value.ToString, ""),gridFont, Brushes.Black, r, sf)
to use FormattedValue:
e.Graphics.DrawString(If(Not DataGridView1.Rows(y).Cells(x).Value Is Nothing, DataGridView1.Rows(y).Cells(x).FormattedValue.ToString, ""),
gridFont, Brushes.Black, r, sf)
alternatively, change it to this to catch the dates and format them manually:
Dim cell As DataGridViewCell = DataGridView1.Rows(y).Cells(x)
Dim formatted As String = ""
If cell.Value IsNot Nothing Then
If cell.ValueType Is GetType(DateTime) Then
formatted = DirectCast(cell.Value, DateTime).ToString("dd/MM/yyyy")
Else
formatted = cell.FormattedValue
End If
End If
e.Graphics.DrawString(formatted, gridFont, Brushes.Black, r, sf)

Positioning of a printed datagridview in vb.net

I've been looking for code that import and print DataGridView and I found it.
My purpose is to make a billing system for law firm.
I've printed the name of the lawyer and the adresse and etc and after that, I want to print the datagridview of the bill but the problem is that, vb print it over the info of lawyer.
my purpose is to print the gatagridview under the lawyer info .
there was a solution on the internet like:
e.Graphics.DrawRectangle(blackPen, New Rectangle(position, yPosition, totalWidth, height))
I have tried hard the implement it in the code but it didn't work
Please help
Private Sub PrintDocument1_PrintPage(sender As System.Object, e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
'lawyer info
e.Graphics.DrawString("Facture", New Font("Arial", 24, FontStyle.Italic), Brushes.Blue, New Point(200, 20))
e.Graphics.DrawString("Nom Avocat : " + TextBox17.Text, New Font("Arial", 12, FontStyle.Italic), Brushes.Black, New Point(20, 60))
e.Graphics.DrawString("Adresse : " + TextBox18.Text, New Font("Arial", 12, FontStyle.Italic), Brushes.Black, New Point(20, 80))
e.Graphics.DrawString("Ville : " + TextBox19.Text, New Font("Arial", 12, FontStyle.Italic), Brushes.Black, New Point(20, 100))
e.Graphics.DrawString("Telephone : " + TextBox20.Text, New Font("Arial", 12, FontStyle.Italic), Brushes.Black, New Point(20, 120))
e.Graphics.DrawString("Email : " + TextBox21.Text, New Font("Arial", 12, FontStyle.Italic), Brushes.Black, New Point(20, 140))
e.Graphics.DrawString("Site web : " + TextBox22.Text, New Font("Arial", 12, FontStyle.Italic), Brushes.Black, New Point(20, 160))
e.Graphics.DrawString("Site web : " + TextBox22.Text, New Font("Arial", 12, FontStyle.Italic), Brushes.Black, New Point(20, 180))
'positioning of datagriview2
'insert datagridview
' 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 = DataGridView2.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 DataGridView2.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(DataGridView2.Columns(cell.ColumnIndex).HeaderText,
DataGridView2.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 DataGridView2.RowCount - 1
' no need to try to print the new row
If DataGridView2.Rows(thisNDX).IsNewRow Then Exit For
row = DataGridView2.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 DataGridView2.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(),
DataGridView2.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 instert
End Sub
End Class
You start printing lawyer info at the absolute coordinates of the paper , then you decide to use Margins !!!
try
Dim y As Int32 = e.MarginBounds.Top
'lawyer info
e.Graphics.DrawString("Facture", New Font("Arial", 24, FontStyle.Italic), Brushes.Blue, New Point(200, 20 + y))
e.Graphics.DrawString("Nom Avocat : " + TextBox17.Text, New Font("Arial", 12, FontStyle.Italic), Brushes.Black, New Point(20, 60 + y))
'....
'your code
I found a code that I edited and now it works fine
there it is:
'second solution
Dim leftMargin As Integer = 100 ' Change value to change the x-position of the DataGridView
Dim position As Integer = leftMargin
Dim yPosition As Integer = 200 ' Change value to change the y-position of the DataGridView
Dim height As Integer = DataGridView2.ColumnHeadersHeight
Dim fmt As StringFormat = New StringFormat(StringFormatFlags.LineLimit)
Dim blackPen As New Pen(Color.Black, 3)
position = leftMargin
yPosition = yPosition + DataGridView2.ColumnHeadersHeight
For Each dr As DataGridViewColumn In DataGridView2.Columns
Dim totalWidth As Double = dr.Width
e.Graphics.FillRectangle(New SolidBrush(Color.White), New Rectangle(position, yPosition, totalWidth, height))
e.Graphics.DrawRectangle(blackPen, New Rectangle(position, yPosition, totalWidth, height))
e.Graphics.DrawString(dr.HeaderText, New Font("Times New Roman", 10, FontStyle.Bold Or FontStyle.Italic), Brushes.Black, position, yPosition, fmt)
position = position + totalWidth
Next
For Each dr As DataGridViewRow In DataGridView2.Rows
position = leftMargin
yPosition = yPosition + DataGridView2.ColumnHeadersHeight
For Each dc As DataGridViewCell In dr.Cells
Dim totalWidth As Double = dc.OwningColumn.Width
e.Graphics.FillRectangle(New SolidBrush(Color.White), New Rectangle(position, yPosition, totalWidth, height))
e.Graphics.DrawRectangle(Pens.Black, New Rectangle(position, yPosition, dc.OwningColumn.Width, height))
e.Graphics.DrawString(dc.Value, New Font("Verdana", 8, FontStyle.Regular), Brushes.Black, position, yPosition)
position = position + totalWidth
Next
Next
End Sub
`

Print to next page

I have read a lot of different posts on printing to more pages in VB.NET. For some reason I'm not getting it to work, however. I have e.hasmorepages set to True once the yPosition goes over 1000. Instead of going to the next page, however, it's overwriting starting from the top. What am I doing wrong here? This is a school project.
Private Sub PrintDocument1_PrintPage(sender As Object, e As Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
'Declare variables for printing position, strings, and state name
Dim yPos As Integer = 40
Dim xPos As Integer = 25
Dim strLine1 As String = String.Empty
Dim strLine2 As String = String.Empty
Dim strLine3 As String = String.Empty
Dim strLine4 As String = String.Empty
Dim strLine5 As String = String.Empty
For i = 0 To (lstRecords.Items.Count - 1)
'Concatenate strings for printing
strLine1 = "Record Name: " & gVinyl(i).Name
strLine2 = "Artist: " & gVinyl(i).Artist
strLine3 = "Released: " & gVinyl(i).Year
strLine4 = "Contains: " & gVinyl(i).Tracks.ToString & " tracks running " & gVinyl(i).Duration & " minutes"
strLine5 = "Size: " & gVinyl(i).Size.ToString & " inches Speed: " & gVinyl(i).Speed.ToString & " RPM"
'Multiple page print
If yPos > 1000 Then
e.HasMorePages = True
yPos = 40
End If
'Position each string line for printing
e.Graphics.DrawString(strLine1, New Font("Times New Roman", 11), Brushes.Black, xPos, yPos)
yPos += 20
e.Graphics.DrawString(strLine2, New Font("Times New Roman", 11), Brushes.Black, xPos, yPos)
yPos += 20
e.Graphics.DrawString(strLine3, New Font("Times New Roman", 11), Brushes.Black, xPos, yPos)
yPos += 20
e.Graphics.DrawString(strLine4, New Font("Times New Roman", 11), Brushes.Black, xPos, yPos)
yPos += 20
e.Graphics.DrawString(strLine5, New Font("Times New Roman", 11), Brushes.Black, xPos, yPos)
yPos += 50
Next
'Last page printed
e.HasMorePages = False
End Sub
Hans answered this:
You have to add Exit Sub so it will start printing the page. Then the event fires again to print the next page. You do not want to start at 0 again. So make i a field of your class. Set it to 0 with the BeginPrint event.
THANK YOU HANS!

How to print multiple page using e.HasMorePages?

I want to print data from datagridview,
however when data exceed than one page it is missing. I try to use e.HasMorePages to print multiple pages. I try and search for example for 3 hours ago but unfortunately it does not work
Now when I click print, It is print only the same page without stopping.
Please help.
Private Sub PrintColorConsumption_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintColorConsumption.PrintPage
Dim x As Integer = 100
Dim y As Integer = 25
Dim header As Boolean = True
'draw headers
Dim j As Integer = 0
Do While (j < Me.DataGridView3.Columns.Count)
Dim rect As Rectangle = New Rectangle(x, y, Me.DataGridView3.Columns(j).Width, Me.DataGridView3.ColumnHeadersHeight)
Dim sf As StringFormat = New StringFormat
sf.LineAlignment = StringAlignment.Center
sf.Alignment = StringAlignment.Center
e.Graphics.FillRectangle(Brushes.LightGray, rect)
e.Graphics.DrawRectangle(Pens.Black, rect)
If (Not (Me.DataGridView3.Columns(j).HeaderText) Is Nothing) Then
e.Graphics.DrawString(Me.DataGridView3.Columns(j).HeaderText, SystemFonts.DefaultFont, Brushes.Black, rect, sf)
End If
x = (x + rect.Width)
j = (j + 1)
Loop
x = 100
y = (y + Me.DataGridView3.ColumnHeadersHeight)
'draw rows
For Each row As DataGridViewRow In Me.DataGridView3.Rows
j = 0
Do While (j < Me.DataGridView3.Columns.Count)
Dim cell As DataGridViewCell
cell = row.Cells(j)
Dim rect As Rectangle = New Rectangle(x, y, cell.Size.Width, cell.Size.Height)
Dim sf As StringFormat = New StringFormat
sf.LineAlignment = StringAlignment.Center
sf.Alignment = StringAlignment.Center
e.Graphics.DrawRectangle(Pens.Black, rect)
If (Not (cell.Value) Is Nothing) Then
e.Graphics.DrawString(cell.Value.ToString, SystemFonts.DefaultFont, Brushes.Black, rect, sf)
End If
x = (x + rect.Width)
j = (j + 1)
Loop
x = 100
y = (y + row.Height)
'----------------------New page----------------------------
If (y > e.MarginBounds.Bottom) Then 'Print new page
e.HasMorePages = True
y = 20
End If
'-----------------------------------------------------------------
Next
End Sub
Printing requires you to maintain where you are within the data that you are printing for every PrintPage event. The way you have your variables declared they go out of scope and are set to their initial values every time the event is raised.
See if the following code, which wasn't tested, helps. Note that a variable was declared outside of the event handler to keep track of the current row.
Dim whRow As Integer = 0
Private Sub PrintColorConsumption_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintColorConsumption.PrintPage
Dim x As Integer = 100
Dim y As Integer = 25
Dim header As Boolean = True
'draw headers
Dim j As Integer = 0
Do While (j < Me.DataGridView3.Columns.Count)
Dim rect As Rectangle = New Rectangle(x, y, Me.DataGridView3.Columns(j).Width, Me.DataGridView3.ColumnHeadersHeight)
Dim sf As StringFormat = New StringFormat
sf.LineAlignment = StringAlignment.Center
sf.Alignment = StringAlignment.Center
e.Graphics.FillRectangle(Brushes.LightGray, rect)
e.Graphics.DrawRectangle(Pens.Black, rect)
If (Not (Me.DataGridView3.Columns(j).HeaderText) Is Nothing) Then
e.Graphics.DrawString(Me.DataGridView3.Columns(j).HeaderText, SystemFonts.DefaultFont, Brushes.Black, rect, sf)
End If
x = (x + rect.Width)
j = (j + 1)
Loop
x = 100
y = (y + Me.DataGridView3.ColumnHeadersHeight)
'draw rows
For whRow = whRow To Me.DataGridView3.RowCount - 1
Dim drow As DataGridViewRow = Me.DataGridView3.Rows(whRow)
j = 0
Do While (j < Me.DataGridView3.Columns.Count)
Dim cell As DataGridViewCell
cell = drow.Cells(j)
Dim rect As Rectangle = New Rectangle(x, y, cell.Size.Width, cell.Size.Height)
Dim sf As StringFormat = New StringFormat
sf.LineAlignment = StringAlignment.Center
sf.Alignment = StringAlignment.Center
e.Graphics.DrawRectangle(Pens.Black, rect)
If (Not (cell.Value) Is Nothing) Then
e.Graphics.DrawString(cell.Value.ToString, SystemFonts.DefaultFont, Brushes.Black, rect, sf)
End If
x = (x + rect.Width)
j = (j + 1)
Loop
x = 100
y = (y + drow.Height)
'----------------------New page----------------------------
If (y > e.MarginBounds.Bottom) Then 'Print new page
e.HasMorePages = True
y = 20
End If
'-----------------------------------------------------------------
Next
End Sub