Batch Printing with condition from DataGridView

305 Views Asked by At

I am trying to batch print data from DataGridView using vb.net, a row per page. The current code just loops. I would like to process and print all rows and get to ask only once where to save the PDF. By the way, I have set the printer to PDF printer. The output should be 6 pages.

This is my code so far.

Imports System.Drawing.Printing
Imports System.Text.RegularExpressions

Public Class Form1
    Public currentRow As Integer
    Public totPages As Integer
    Public pageNumber As Integer
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        For i As Integer = 0 To 5
            DataGridView1.Rows.Add("Yes", "someData" & i, "someData" & i, "someData" & i, "someData" & i)
        Next


    End Sub
    Private Sub printButton_Click(sender As Object, e As EventArgs) Handles printButton.Click
        Dim pdS As New PrintDocument()

        pdS.DefaultPageSettings.Landscape = False

        Dim PrintDialog1 As New PrintDialog
        PrintDialog1.Document = pdS
        totPages = 0
        pageNumber = 0
        For Each row As DataGridViewRow In DataGridView1.Rows
            If row.Cells(0).Value = "Yes" Then
                totPages = totPages + 1
            End If
        Next

        AddHandler pdS.PrintPage, AddressOf pds_PrintPage

        If (PrintDialog1.ShowDialog = DialogResult.OK) Then
            For Each row As DataGridViewRow In DataGridView1.Rows
                If row.Cells(0).Value = "Yes" Then
                    currentRow = row.Index
                    pageNumber = pageNumber + 1
                    pdS.Print()
                End If
            Next
        End If

    End Sub

    Private Sub pds_PrintPage(sender As Object, ev As PrintPageEventArgs)

        'Drawing
        Dim inputData As String
        Dim calReg As New Font("Calibri", 8, FontStyle.Regular)
        With DataGridView1
            inputData = .Rows(currentRow).Cells(1).Value & vbCrLf & .Rows(currentRow).Cells(2).Value & vbCrLf &
                .Rows(currentRow).Cells(3).Value & vbCrLf & .Rows(currentRow).Cells(4).Value
        End With

        Dim nextY As Double
        nextY = ev.MarginBounds.Y
        ev.Graphics.DrawString(inputData, calReg, Brushes.Black, ev.MarginBounds.X, nextY)

        If totPages > pageNumber Then
            ev.HasMorePages = True
            Exit Sub
        Else
            ev.HasMorePages = False
        End If

    End Sub
End Class


1

There are 1 best solutions below

1
AudioBubble On

You can create a Queue of the target DataGridViewRow objects, dequeue a row in the PrintPage handler to print it, and set the HasMorePages property to True if the queue has more rows.

The method below is to print or preview.

Private Sub Print(Optional IsPreview As Boolean = False)
    Using pdoc As New PrintDocument,
            pd As New PrintDialog With {.Document = pdoc},
            pp As New PrintPreviewDialog With {.Document = pdoc}

        pdoc.DefaultPageSettings.Landscape = False

        If Not IsPreview AndAlso pd.ShowDialog <> DialogResult.OK Then Return

        Dim q As New Queue(Of DataGridViewRow)

        DataGridView1.Rows.Cast(Of DataGridViewRow).
            Where(Function(r) Not r.IsNewRow AndAlso r.Cells(0).Value.ToString = "Yes").
            ToList.ForEach(Sub(r) q.Enqueue(r))

        AddHandler pdoc.PrintPage,
            Sub(s, e)
                Using f As New Font("Calibri", 8, FontStyle.Regular)
                    Dim r = q.Dequeue
                    Dim x = e.MarginBounds.X
                    Dim y = e.MarginBounds.Y

                    For Each cell In r.Cells.Cast(Of DataGridViewCell).Skip(1)
                        e.Graphics.DrawString(cell.Value.ToString, f, Brushes.Black, x, y)
                        y += f.Height
                    Next

                    e.HasMorePages = q.Count > 0
                End Using
            End Sub

        If IsPreview Then
            pp.ShowDialog()
        Else
            pdoc.Print()
        End If
    End Using
End Sub

This will printout 6 pages for the given example. Call the method as follows:

Private Sub printButton_Click(sender As Object, e As EventArgs) Handles printButton.Click
    Print() 'To print...
    Print(True) 'To preview...
End Sub