Search code examples
vb.netformsprintingprintdocument

How to multipage duplex print with multiple Windows Forms in Visual Basic?


I'm trying to find a way to print multiple Windows Forms as a report. I have multiple forms that calculate the retirement benefits of our clients and I'm trying to print those forms so our clients get handouts. At this point I have on each form a PrintDocument component and I can print each form on seperate pages as different documents, but what I'm trying to achieve is to duplex print all those forms in 1 PrintDocument document with 1 single PrintButton.Click on yet another form.

So to give you an example. I have 2 Windows Forms (Form AOW and form Basisinfo) with each a PrintDocument component. I have drawn the texts, images, charts, etc. just the way it should be with the right positions in the PrintDocument1_PrintPage sub. I want to print forms AOW and Basisinfo at a third form called CloseReport.

The code I already have which gives me no duplex prints:

Basisinfo:

Public Class Basisinfo


Private Sub Button2_Click(sender As Object, e As EventArgs) Handles ButtonPrinten.Click

    For teller = 1 To 30
        If inhoudlijst(teller, 0) = "" Then
            inhoudlijst(teller, 0) = "Basisinfo"
            inhoudlijst(teller, 1) = "True"
            PrintDocument1.DefaultPageSettings.Landscape = True
            PrintDocument1.DefaultPageSettings.PrinterSettings.Duplex = Printing.Duplex.Default
            printarray3(teller) = PrintDocument1
            Exit For
        End If
    Next
End Sub


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

    Dim stringFormatCenter As New StringFormat()
    stringFormatCenter.Alignment = StringAlignment.Center
    stringFormatCenter.LineAlignment = StringAlignment.Center

    Dim stringFormatFar As New StringFormat()
    stringFormatFar.Alignment = StringAlignment.Far
    stringFormatFar.LineAlignment = StringAlignment.Center

    Dim stringFormatNear As New StringFormat()
    stringFormatNear.Alignment = StringAlignment.Near
    stringFormatNear.LineAlignment = StringAlignment.Center


    'Alle TextBoxes met witte achtergrond
    For Each TextBox In {TextBox17, TextBox18, TextBox35, TextBox1, TextBox29, TextBox2, TextBox3, TextBox4, TextBox12, TextBox13, TextBox10, TextBox9, TextBox26, TextBox8, TextBox7, TextBox16, TextBox21, TextBox14, TextBox28, TextBox27, TextBox6, TextBox23, TextBox19, TextBox31, TextBox24, TextBox25, TextBox30, TextBox15, TextBox34, TextBox22, TextBox20, TextBox33, TextBox32}
        e.Graphics.DrawRectangle(Pens.Black, New Rectangle(TextBox.Left, TextBox.Top, TextBox.Width, TextBox.Height))
        e.Graphics.FillRectangle(Brushes.White, TextBox.Left, TextBox.Top, TextBox.Width, TextBox.Height)
    Next

    'Alle TextbBoxes met gele achtergrond
    For Each TextBox In {TextBox17, TextBox18, TextBox35, TextBox1, TextBox29}
        e.Graphics.FillRectangle(Brushes.LightYellow, TextBox.Left, TextBox.Top, TextBox.Width, TextBox.Height)
    Next


    'Textboxes Centered
    For Each TextBox In {TextBox17, TextBox18, TextBox35, TextBox1, TextBox29}
        e.Graphics.DrawString(TextBox.Text, TextBox.Font, Brushes.Blue, New Rectangle(TextBox.Left, TextBox.Top, TextBox.Width, TextBox.Height), stringFormatCenter)
    Next

    'Textboxes Near
    For Each TextBox In {TextBox2, TextBox3, TextBox4, TextBox12, TextBox13, TextBox10, TextBox9, TextBox26, TextBox8, TextBox7, TextBox16, TextBox21, TextBox14, TextBox28, TextBox27, TextBox6, TextBox23, TextBox19, TextBox31, TextBox24, TextBox25, TextBox30, TextBox15, TextBox34, TextBox22, TextBox20, TextBox33, TextBox32}
        e.Graphics.DrawString(TextBox.Text, TextBox.Font, Brushes.Blue, New Rectangle(TextBox.Left, TextBox.Top, TextBox.Width + 20, TextBox.Height), stringFormatNear)
    Next


    'Textboxes Far
    For Each TextBox In {}
        e.Graphics.DrawString(TextBox.Text, TextBox.Font, Brushes.Blue, New Rectangle(TextBox.Left, TextBox.Top, TextBox.Width, TextBox.Height), stringFormatFar)
    Next



    For Each c As Control In Me.Controls
        If c.GetType Is GetType(Label) Then
            e.Graphics.DrawString(c.Text, c.Font, Brushes.Black, c.Left, c.Top)
        End If
    Next
End Sub

AOW:

Public Class AOW

Sub ButtonPrinten_Click(sender As Object, e As EventArgs) Handles ButtonPrinten.Click

    For teller = 1 To 30
        If inhoudlijst(teller, 0) = "" Then
            inhoudlijst(teller, 0) = "AOW"
            inhoudlijst(teller, 1) = "True"
            PrintDocument1.DefaultPageSettings.Landscape = True
            PrintDocument1.DefaultPageSettings.PrinterSettings.Duplex = Printing.Duplex.Default
            printarray3(teller) = PrintDocument1
            'printvlag_basisinfo = True
            Exit For
        End If
    Next

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

    Dim stringFormatCenter As New StringFormat()
    stringFormatCenter.Alignment = StringAlignment.Center
    stringFormatCenter.LineAlignment = StringAlignment.Center

    Dim stringFormatFar As New StringFormat()
    stringFormatFar.Alignment = StringAlignment.Far
    stringFormatFar.LineAlignment = StringAlignment.Center

    Dim stringFormatNear As New StringFormat()
    stringFormatNear.Alignment = StringAlignment.Near
    stringFormatNear.LineAlignment = StringAlignment.Center

    'Alle TextBoxes met witte achtergrond
    For Each TextBox In {Koptextbox, TextBox99, TextBox19, TextBox21, TextBox11, TextBox12, TextBox14, TextBox13, TextBox17, TextBox15, TextBox16, TextBox18}
        e.Graphics.DrawRectangle(Pens.Black, New Rectangle(TextBox.Left, TextBox.Top, TextBox.Width, TextBox.Height))
        e.Graphics.FillRectangle(Brushes.White, TextBox.Left, TextBox.Top, TextBox.Width, TextBox.Height)
    Next

    'Alle TextbBoxes met gele achtergrond
    For Each TextBox In {Koptextbox, TextBox99, TextBox19, TextBox21, TextBox13, TextBox17, TextBox18, TextBox16}
        e.Graphics.FillRectangle(Brushes.LightYellow, TextBox.Left, TextBox.Top, TextBox.Width, TextBox.Height)
    Next

    'Textboxes Centered
    For Each TextBox In {Koptextbox, TextBox99, TextBox21, TextBox19, TextBox14, TextBox13, TextBox17, TextBox15, TextBox16, TextBox18}
        e.Graphics.DrawString(TextBox.Text, TextBox.Font, Brushes.Blue, New Rectangle(TextBox.Left, TextBox.Top, TextBox.Width, TextBox.Height), stringFormatCenter)
    Next

    'Textboxes Near
    For Each TextBox In {TextBox1, TextBox2, TextBox3, TextBox4, TextBox5, TextBox6, TextBox7, TextBox8, TextBox9, TextBox10, TextBox11, TextBox24, TextBox23, TextBox22}
        e.Graphics.DrawString(TextBox.Text, TextBox.Font, Brushes.Blue, New Rectangle(TextBox.Left, TextBox.Top, TextBox.Width + 20, TextBox.Height), stringFormatNear)
    Next


    'Textboxes Far
    For Each TextBox In {TextBox12}
        e.Graphics.DrawString(TextBox.Text, TextBox.Font, Brushes.Blue, New Rectangle(TextBox.Left, TextBox.Top, TextBox.Width, TextBox.Height), stringFormatFar)
    Next

    For Each c As Control In Me.Controls
        If c.GetType Is GetType(Label) Then
            e.Graphics.DrawString(c.Text, c.Font, Brushes.Black, c.Left, c.Top)
        End If
    Next

End Sub
End Class

CloseReport:

Public Class CloseReport


Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click

    PrintDocument1.DefaultPageSettings.Landscape = True
    PrintDialog1.Document = PrintDocument1
    If PrintDialog1.ShowDialog() = DialogResult.OK Then
        For teller = 1 To 30
            If IsNothing(printarray3(teller)) = False Then
                printen6(printarray3(teller))
            End If
        Next teller
    End If
End Sub
End Class

If you want to know what the printen6 function does:

    PrintDocument.PrinterSettings.DefaultPageSettings.PrinterResolution.Kind = Printing.PrinterResolutionKind.High
    PrintDocument.PrinterSettings.DefaultPageSettings.Landscape = True
    PrintDocument.PrinterSettings.DefaultPageSettings.Margins = New Printing.Margins(0, 0, 0, 0)

    PrintDocument.DefaultPageSettings.PrinterSettings.Duplex = Printing.Duplex.Default


    PrintDocument.Print()

I'm either thinking of how to merge PrintDocument files so duplex printing is possible, or how to create multiple pages with HasMorePages. I've read quite some about HasMorePages on the web, but that only provides code with textfiles being loaded..

I hope you can help me out, since I'm really stuck at this. Thanks in advance!


Solution

  • For those who are interested in the answer: It was e.HasMorePages = True.. But the only thing that was missing was a (Public) 'PageNumber' counter which made it possible to select between cases. It is important for e.HasMorePages to reach the end of the Sub. Otherwise it won't have effect. See the code below.

    Public Class Inhoudsopgave
    Dim PageNumber As Integer = 0
    Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
    
        PrintDocument1.DefaultPageSettings.Margins = New Printing.Margins(0, 0, 0, 0)
        PrintDocument1.DefaultPageSettings.Landscape = True
        PrintDialog1.Document = PrintDocument1 'PrintDialog associate with PrintDocument.
        If PrintDialog1.ShowDialog() = DialogResult.OK Then
            PrintDocument1.Print()
        End If
    End Sub
    
    Private Sub PrintDocument1_PrintPage(sender As Object, e As Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
    
        PrintDocument1.DefaultPageSettings.Margins = New Printing.Margins(0, 0, 0, 0)
    
        Select Case PageNumber
            Case 0
                For Each c As Control In Me.Controls
                    If c.GetType Is GetType(Label) Then
                        e.Graphics.DrawString(c.Text, c.Font, Brushes.Black, c.Left, c.Top)
                    End If
                    e.HasMorePages = True
                Next
            Case 1
                'aow
                Dim stringFormatCenter As New StringFormat()
                stringFormatCenter.Alignment = StringAlignment.Center
                stringFormatCenter.LineAlignment = StringAlignment.Center
    
                Dim stringFormatFar As New StringFormat()
                stringFormatFar.Alignment = StringAlignment.Far
                stringFormatFar.LineAlignment = StringAlignment.Center
    
                Dim stringFormatNear As New StringFormat()
                stringFormatNear.Alignment = StringAlignment.Near
                stringFormatNear.LineAlignment = StringAlignment.Center
    
    
                'Doe dit voor iedere Groupbox en Chart
                Dim BMPGroupbox1 As Bitmap = New Bitmap(AOW.GroupBox1.Width, AOW.GroupBox1.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
                Dim BMPGroupbox2 As Bitmap = New Bitmap(AOW.GroupBox2.Width, AOW.GroupBox2.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
                Dim BMPGroupbox3 As Bitmap = New Bitmap(AOW.GroupBox3.Width, AOW.GroupBox3.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
                Dim BMPChart1 As Bitmap = New Bitmap(AOW.Chart1.Width, AOW.Chart1.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
    
                'Doe dit voor iedere Groupbox en Chart
                AOW.GroupBox1.DrawToBitmap(BMPGroupbox1, New Rectangle(0, 0, AOW.GroupBox1.Width, AOW.GroupBox1.Height))
                AOW.GroupBox2.DrawToBitmap(BMPGroupbox2, New Rectangle(0, 0, AOW.GroupBox2.Width, AOW.GroupBox2.Height))
                AOW.GroupBox3.DrawToBitmap(BMPGroupbox3, New Rectangle(0, 0, AOW.GroupBox3.Width, AOW.GroupBox3.Height))
                AOW.Chart1.DrawToBitmap(BMPChart1, New Rectangle(0, 0, AOW.Chart1.Width, AOW.Chart1.Height))
    
                'Doe dit voor iedere Groupbox en Chart
                e.Graphics.DrawImage(BMPGroupbox1, AOW.GroupBox1.Left, AOW.GroupBox1.Top, AOW.GroupBox1.Width, AOW.GroupBox1.Height)
                e.Graphics.DrawImage(BMPGroupbox2, AOW.GroupBox2.Left, AOW.GroupBox2.Top, AOW.GroupBox2.Width, AOW.GroupBox2.Height)
                e.Graphics.DrawImage(BMPGroupbox3, AOW.GroupBox3.Left, AOW.GroupBox3.Top, AOW.GroupBox3.Width, AOW.GroupBox3.Height)
                e.Graphics.DrawImage(BMPChart1, AOW.Chart1.Left, AOW.Chart1.Top, AOW.Chart1.Width, AOW.Chart1.Height)
    
                'Alle TextBoxes met witte achtergrond
                For Each TextBox In {AOW.Koptextbox, AOW.TextBox99, AOW.TextBox19, AOW.TextBox21, AOW.TextBox11, AOW.TextBox12, AOW.TextBox14, AOW.TextBox13, AOW.TextBox17, AOW.TextBox15, AOW.TextBox16, AOW.TextBox18}
                    e.Graphics.DrawRectangle(Pens.Black, New Rectangle(TextBox.Left, TextBox.Top, TextBox.Width, TextBox.Height))
                    e.Graphics.FillRectangle(Brushes.White, TextBox.Left, TextBox.Top, TextBox.Width, TextBox.Height)
                Next
    
                'Alle TextbBoxes met gele achtergrond
                For Each TextBox In {AOW.Koptextbox, AOW.TextBox99, AOW.TextBox19, AOW.TextBox21, AOW.TextBox13, AOW.TextBox17, AOW.TextBox18, AOW.TextBox16}
                    e.Graphics.FillRectangle(Brushes.LightYellow, TextBox.Left, TextBox.Top, TextBox.Width, TextBox.Height)
                Next
    
                'Textboxes Centered
                For Each TextBox In {AOW.Koptextbox, AOW.TextBox99, AOW.TextBox21, AOW.TextBox19, AOW.TextBox14, AOW.TextBox13, AOW.TextBox17, AOW.TextBox15, AOW.TextBox16, AOW.TextBox18}
                    e.Graphics.DrawString(TextBox.Text, TextBox.Font, Brushes.Blue, New Rectangle(TextBox.Left, TextBox.Top, TextBox.Width, TextBox.Height), stringFormatCenter)
                Next
    
                'Textboxes Near
                For Each TextBox In {AOW.TextBox1, AOW.TextBox2, AOW.TextBox3, AOW.TextBox4, AOW.TextBox5, AOW.TextBox6, AOW.TextBox7, AOW.TextBox8, AOW.TextBox9, AOW.TextBox10, AOW.TextBox11, AOW.TextBox24, AOW.TextBox23, AOW.TextBox22}
                    e.Graphics.DrawString(TextBox.Text, TextBox.Font, Brushes.Blue, New Rectangle(TextBox.Left, TextBox.Top, TextBox.Width + 20, TextBox.Height), stringFormatNear)
                Next
    
                'Textboxes Far
                For Each TextBox In {AOW.TextBox12}
                    e.Graphics.DrawString(TextBox.Text, TextBox.Font, Brushes.Blue, New Rectangle(TextBox.Left, TextBox.Top, TextBox.Width, TextBox.Height), stringFormatFar)
                Next
    
                For Each c As Control In AOW.Controls
                    If c.GetType Is GetType(Label) Then
                        e.Graphics.DrawString(c.Text, c.Font, Brushes.Black, c.Left, c.Top)
                    End If
                Next
    
                e.HasMorePages = False
        End Select
    
        PageNumber += 1
    End Sub
    End Class