Search code examples
vb.netlistviewprinting

How can i get multible page print working


How can I get multiple paper prints when one paper is full.

When I print, I want it to print the current pages needed depending on how much it needs to print, right now I get it to count print pages (See image) until I press cancel and then nothing more.

Page print count

The code I use.

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

    Dim Head As Integer = 0
    Dim List As Integer

    Head += 30
    For List = 0 To ListView1.Items.Count - 1
    Next
    e.Graphics.DrawString("Pocket bok collection", New Drawing.Font("Times new roman", 20), Brushes.Black, 250, Head)
    Head += 40
    e.Graphics.DrawString("Pocket Serie Name", New Drawing.Font("Times new roman", 10), Brushes.Black, 50, Head)
    e.Graphics.DrawString("Single/Double", New Drawing.Font("Times new roman", 10), Brushes.Black, 100, Head)
    e.Graphics.DrawString("Pocket Nr", New Drawing.Font("Times new roman", 10), Brushes.Black, 200, Head)
    e.Graphics.DrawString("Year", New Drawing.Font("Times new roman", 10), Brushes.Black, 300, Head)
    e.Graphics.DrawString("Bought Date", New Drawing.Font("Times new roman", 10), Brushes.Black, 450, Head)
    e.Graphics.DrawString("Cost", New Drawing.Font("Times new roman", 10), Brushes.Black, 550, Head)
    e.Graphics.DrawString("Own", New Drawing.Font("Times new roman", 10), Brushes.Black, 650, Head)

    List += 60

    'Multiple page print
    If List > 1000 Then
        e.HasMorePages = True

    End If

    For Each Itm As ListViewItem In ListView1.Items
        e.Graphics.DrawString(Itm.Text, New Drawing.Font("Times new roman", 10), Brushes.Black, 50, List)
        e.Graphics.DrawString(Itm.SubItems(1).Text, New Drawing.Font("Times new roman", 10), Brushes.Black, 100, List)
        e.Graphics.DrawString(Itm.SubItems(2).Text, New Drawing.Font("Times new roman", 10), Brushes.Black, 200, List)
        e.Graphics.DrawString(Itm.SubItems(3).Text, New Drawing.Font("Times new roman", 10), Brushes.Black, 300, List)
        e.Graphics.DrawString(Itm.SubItems(4).Text, New Drawing.Font("Times new roman", 10), Brushes.Black, 450, List)
        e.Graphics.DrawString(Itm.SubItems(5).Text, New Drawing.Font("Times new roman", 10), Brushes.Black, 550, List)
        e.Graphics.DrawString(Itm.SubItems(6).Text, New Drawing.Font("Times new roman", 10), Brushes.Black, 650, List)

        List += 30

    Next

    e.HasMorePages = True


End Sub

Solution

  • The code that goes in the PrintPage event handler is for printing one page only. If you want to calculate how many pages there are going to be, handle the BeginPrint event and do that there.

    You cannot use a For Each loop over a list in the PrintPage event handler because you're not printing the entire list. You should be using a For loop that starts at the first item index for the current page and ends at the last item index for the current page. An alternative might be to use the Skip and Take methods to get one page worth of items first, then use a For Each loop over that. You need to keep track of the page number to print OUTSIDE the PrintPage event handler, because it has to persist across multiple invocations. E.g.

    Private Const itemsPerPage As Integer = 10
    
    Private pageCount As Integer
    Private lastPrintedPageNumber As Integer
    
    Private Sub PrintDocument1_BeginPrint(sender As Object, e As PrintEventArgs) Handles PrintDocument1.BeginPrint
        Dim itemCount = ListView1.Items.Count
    
        'Divide the total item count by the item count per page and round up to get the number of pages.
        pageCount = Convert.ToInt32(Math.Ceiling(itemCount / itemsPerPage))
    
        'We have not printed any pages yet.
        lastPrintedPageNumber = 0
    End Sub
    
    Private Sub PrintDocument1_PrintPage(sender As Object, e As Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
        'Get the items to print on the current page.
        'Skip the items already printed on previous pages and take the items for this page.
        Dim items = ListView1.Items.Cast(Of ListViewItem)().Skip(lastPrintedPageNumber * itemsPerPage).Take(itemsPerPage)
    
        For Each item In items
            'Print item here.
        Next
    
        'We have printed one more page.
        lastPrintedPageNumber += 1
    
        'There are more pages to print if and only if we didn't just print the last page.
        e.HasMorePages = (lastPrintedPageNumber < pageCount)
    End Sub
    

    Note that the value you pass to Take is the maximum number of items to take. It can handle situations where there are fewer items available, so this code will handle a partially full last page.

    Also note that this code basically assumes that there is at least one page to print. If there are no items to print, pageCount would be 0 but a single blank page would be output. You should probably confirm that there is data to print before calling Print.