Help with Print Document

If you need help with a project or need to know how to do something specific in VB.NET then please ask your questions in here.
Forum rules
Please LOCK your topics once you have found the solution to your question so we know you no longer require help with your query.
5 posts Page 1 of 1
Contributors
User avatar
Dummy1912
VIP - Donator
VIP - Donator
Posts: 1969
Joined: Sat Aug 21, 2010 2:17 pm

Help with Print Document
Dummy1912
Hello,

i can't get it fix to print on multi pages
i tried and changed almost everything i can find but didn't work

can anybody helpme out please

i just want the to display on 1 page like 8 records and then the total result
if more records the total result will be on the other last page but still all the pages has to be like 8 records
Thank you

'Print
Code: Select all

Imports System.Drawing.Drawing2D
Imports System.Drawing.Printing
Imports System.Drawing.Text

''' <summary>
''' Print transactions class
''' By FFenixW0rks 8.02.2015
''' For great bud - Dummy1912 (I3C)
''' Now this code belongs to I3C if credits are given(only in code! =) )
''' 
''' Enjoy!
''' </summary>
''' <remarks></remarks>

Public Class PrintTransactions

    Friend WithEvents PrintDocument1 As PrintDocument = New PrintDocument()
    Friend WithEvents PrintPreviewDialog1 As PrintPreviewDialog = New PrintPreviewDialog()
    Friend WithEvents PrintDialog1 As System.Windows.Forms.PrintDialog = New PrintDialog()

    'Array of transactions
    Private tr() As TransactionsData

    Public Class TransactionsData
        'Sets description of transaction
        Friend trDescr As String
        'Set date of it
        Friend trDate As Date
        'And value
        Friend trValue As Double
        'Anything could be added. For printing/for any usage. Just upper three should be as they are.

        Property trID As Integer

    End Class

    'Transaction count will be actually transCount. 
    'Okay, readed info about them.. actually transCount will be max index
    'DO NOT CHANGE!
    Private _trCount = 0
    Public Property transCount As Integer
        Get
            Return _trCount
        End Get
        Private Set(value As Integer)
            ReDim tr(value)
            _trCount = value
        End Set
    End Property

    'To draw or not to draw picture on top(trademark, watermark, etc)
    'NOTICE: If false non of image on top nor text in the bottom would be drawn !
    Private DrawTm As Boolean = True

#Region "Dev Vars"

    'Transactions sub total value
    Private trSubTotal As Double = 0
    'Without external count variable Print preview would print infinite pages
    Private count As Integer = 0

    'Transactions sub total
    Private subTotal As Double = 0.0

    'Page number
    Private pageNum As Integer = 1
    'Total pages count
    Private totalPages As Integer = 0

    'Start postition of table(basicly start point of rectangle). Page margin will be included after!
    Private strtPoint As Point = New Point(30, 55)
    'Adding page margin to start position. Will be updated later in code with height
    Private sPoint As Point
    'Size of rectangle. Width should be = Height!(if rectangle wanted)
    Private sSize As Size = New Size(20, 20)
    Friend Shared trCountEvents As List(Of String) = New List(Of String)

#End Region
#Region " New "
    Public Sub New()
        PrintPreviewDialog1.Document = PrintDocument1

        ReDim tr(transCount)
        Dim PS As New Printing.PageSettings
        With PS
            .Margins.Bottom = 10
            .Margins.Right = 20
            .Margins.Left = 20
            .Margins.Top = 20
        End With
        PrintDocument1.DefaultPageSettings = PS
        PrintPreviewDialog1.WindowState = FormWindowState.Maximized
        Try
        Catch ex As Exception

        End Try
    End Sub

    Public Sub New(ByVal trans() As TransactionsData)
        PrintPreviewDialog1.Document = PrintDocument1
        transCount = trans.Length - 1
        ReDim tr(trans.Length - 1)
        tr = trans ' Copying our data to local array

        Dim PS As New Printing.PageSettings
        With PS
            .Margins.Bottom = 10
            .Margins.Right = 10
            .Margins.Left = 10
            .Margins.Top = 10
        End With
        PrintDocument1.DefaultPageSettings = PS
        PrintPreviewDialog1.WindowState = FormWindowState.Maximized
        Try
        Catch ex As Exception

        End Try
    End Sub
#End Region

    Private Sub PrintDocument1_BeginPrint(sender As Object, e As PrintEventArgs) Handles PrintDocument1.BeginPrint
        count = 0
        pageNum = 1
        subTotal = 0
    End Sub

    'To print at top or between
    Private Sub PrintInfo(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs)
        Dim fnt As Font

        ''Info
        e.Graphics.DrawString("Address : " & vbNewLine & "Address2 :", New Font("Arial", 10), Brushes.Black, 180, 80)
        e.Graphics.DrawString("Email Address : ", New Font("Arial", 10), Brushes.Black, 180, 110)
        e.Graphics.DrawString("Phone : ", New Font("Arial", 10), Brushes.Black, 180, 125)

        ''invoice nr
        fnt = New Font("Arial", 10, FontStyle.Regular)
        e.Graphics.DrawString("Invoice# ", fnt, Brushes.Black, 180, 150)

        ''Set Print Date Time
        fnt = New Font("Arial", 10, FontStyle.Regular)
        Dim dt As DateTime = DateTime.Now
        e.Graphics.DrawString("Date : " & dt.ToString("MM/d/yy"), fnt, Brushes.Black, 180, 165)

    End Sub

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

        If totalPages = 0 Then
            CountPages(e)
        End If
        Dim SF As StringFormat = New StringFormat()
        SF.Trimming = StringTrimming.Word
        'Font for strings
        Dim fnt As New Font("Arial", 7)
        'Better graphics
        e.Graphics.TextRenderingHint = TextRenderingHint.AntiAlias
        e.Graphics.SmoothingMode = SmoothingMode.AntiAlias

        'Set start point
        sPoint = New Point(strtPoint.X + e.MarginBounds.Left, strtPoint.Y + e.MarginBounds.Top)
 
        PrintInfo(sender, e)

        'Start Line
        e.Graphics.FillRectangle(Brushes.DarkGray, e.MarginBounds.Width - 220, 225, 195, 30)
        e.Graphics.DrawString("Payment Due: 02/02/10", New Font("Arial", 12, FontStyle.Bold), Brushes.White, e.MarginBounds.Width - 218, 230)

        e.Graphics.DrawString("ACCOUNT", New Font("Arial", 12, FontStyle.Bold), Brushes.Black, 70, 280)
        e.Graphics.DrawString("SUBTOTAL", New Font("Arial", 12, FontStyle.Bold), Brushes.Black, e.MarginBounds.Width - 300, 280)
        e.Graphics.DrawString("WALLET", New Font("Arial", 12, FontStyle.Bold), Brushes.Black, e.MarginBounds.Width - 100, 280)

      For i As Integer = count To transCount

            'As element could be possible null - lets check for it
            If IsNothing(tr(i)) Then Continue For

            'Write description
            Dim descSize As SizeF = e.Graphics.MeasureString(tr(i).trDescr, fnt)
            Dim replaceDesc As String
            replaceDesc = tr(i).trDescr
            replaceDesc = Strings.Replace(replaceDesc, vbNewLine, " ")
            Dim Rectf As RectangleF = New Rectangle(90, 290 + sPoint.Y, descSize.Width - sPoint.X - 45, sSize.Height + 15)
            e.Graphics.DrawString(replaceDesc, fnt, Brushes.Black, Rectf, SF)


            'Make line lower then description. Could be better.
            Dim Height As Integer = 0
            If sSize.Height * 3 + CInt(Math.Round(sSize.Height / 2)) > descSize.Height Then ' + sPoint.Y
                Height = sPoint.Y + 240 + CInt(Math.Round(sSize.Height / 2))
            Else
                Height = sPoint.Y + sSize.Height + (descSize.Height - CInt(Math.Round(sSize.Height / 2))) ' + CInt(Math.Round(sSize.Height / 2))
                sPoint = New Point(sPoint.X, sPoint.Y + (descSize.Height - CInt(Math.Round(sSize.Height / 2)) - CInt(sSize.Height * 2.5)))
            End If

            e.Graphics.FillRectangle(Brushes.DarkGray, New Rectangle(50, Height, e.MarginBounds.Width - sPoint.X - 35, 30))
            'write account
            Dim accSize As SizeF = e.Graphics.MeasureString("Codenstuff and crew", New Font("Arial", 10, FontStyle.Bold))
            Dim Rf As RectangleF = New Rectangle(70, 258 + sPoint.Y, 0, 0)
            e.Graphics.DrawString("Codenstuff and crew", New Font("Arial", 10, FontStyle.Bold), Brushes.Black, Rf, SF)

            'write amount
            Dim amountSize As SizeF = e.Graphics.MeasureString("150.00€", New Font("Arial", 10, FontStyle.Bold))
            Dim Af As RectangleF = New Rectangle(e.MarginBounds.Width - 300, 258 + sPoint.Y, 0, 0)
            e.Graphics.DrawString("150.00€", New Font("Arial", 10, FontStyle.Bold), Brushes.Black, Af, SF)

            'write wallet
            Dim WallSize As SizeF = e.Graphics.MeasureString("150.00€", New Font("Arial", 10, FontStyle.Bold))
            Dim Wf As RectangleF = New Rectangle(e.MarginBounds.Width - 90, 258 + sPoint.Y, 0, 0)
            e.Graphics.DrawString("150.00€", New Font("Arial", 10, FontStyle.Bold), Brushes.Black, Wf, SF)

            'sPoint with sub total should be last!
            sPoint = New Point(sPoint.X, sPoint.Y + sSize.Height * 4)
            'Add transaction value to total
            subTotal += tr(i).trValue
            'Set counter
            count = i

            'Add pages if total height of print is more than page height (size)
            If count < transCount Then
                If (sPoint.Y + sSize.Height * 4 + e.Graphics.MeasureString(tr(i + 1).trDescr, fnt).Height + e.Graphics.MeasureString("PageNum1", fnt).Height * 3 > e.MarginBounds.Height) Then
                    e.HasMorePages = True
                    'Resets point height
                    sPoint = New Point(strtPoint.X + e.MarginBounds.Left, strtPoint.Y + e.MarginBounds.Top)
                    'End printing on same page to start a new one
                    count = i + 1
                    Continue For
                    'Exit For
                End If
            ElseIf count = transCount Then
                'Start point for sub total rectangle
                fnt = New Font("Arial", 12, FontStyle.Bold)
                Dim sTSize As SizeF = e.Graphics.MeasureString("Total " & Format(subTotal, "c"), fnt)
                sPoint = New Point((e.MarginBounds.Right / 2 + e.MarginBounds.Left / 2), e.MarginBounds.Bottom - 110)
                e.Graphics.DrawString("Total " & Format(subTotal, "c"), fnt, Brushes.Black,
                e.MarginBounds.Width - sTSize.Width - 30, sPoint.Y + sTSize.Height / 2)
                e.HasMorePages = False
            End If

        Next
        fnt = New Font("Arial", 7)
        'Draw page number
        Dim pnumSize As SizeF = e.Graphics.MeasureString(pageNum.ToString() & " of " & totalPages, fnt)
        'X and Y coodrs are *2 just for number be more visible. Could be covered with line from transaction
        e.Graphics.DrawString(pageNum.ToString() & " of " & totalPages, fnt, Brushes.Black, e.MarginBounds.Right - pnumSize.Width * 2, e.MarginBounds.Height - pnumSize.Height * 2)
        pageNum += 1

        Dim dt As DateTime = DateTime.Now
        Dim pdateSize As SizeF = e.Graphics.MeasureString(dt.ToString("yyyy-MM-dd HH:mm:ss"), fnt)
        'X and Y coodrs are *2 just for number be more visible. Could be covered with line from transaction
        e.Graphics.DrawString(dt.ToString("yyyy-MM-dd HH:mm:ss"), fnt, Brushes.Black, e.MarginBounds.Left - pdateSize.Width / 2 + 100, e.MarginBounds.Height - pdateSize.Height * 2)
        'PrintFooter(sender, e)

    End Sub

    Private Sub CountPages(ev As PrintPageEventArgs)
        Dim e As PrintPageEventArgs = ev
        totalPages = 1
        Dim cnt = count
        Dim transcnt = transCount
        Dim SF As StringFormat = New StringFormat()
        SF.Trimming = StringTrimming.Word
        'Font for strings
        Dim fnt As New Font("Arial", 7)
        e.Graphics.TextRenderingHint = TextRenderingHint.AntiAlias

        'Set start point
        Dim sPoint2 As Point = New Point(strtPoint.X + e.MarginBounds.Left, strtPoint.Y + e.MarginBounds.Top)

        'Go for every trnsaction in our array
        For i As Integer = cnt To transcnt

            'As element could be possible null - lets check for it
            If IsNothing(tr(i)) Then Continue For

            fnt = New Font("Arial", 7)
            Dim descSize As SizeF = e.Graphics.MeasureString(tr(i).trDescr, fnt)
            '                   ---- >>>                                                            \/\/\/\/\/\/\/\/ - Should be value that will show how much description is righter then datetime rectangle
            Dim Height As Integer = 0
            If sSize.Height * 3 + CInt(Math.Round(sSize.Height / 2)) > descSize.Height Then ' + sPoint2.Y
                Height = sPoint2.Y + sSize.Height * 3 + CInt(Math.Round(sSize.Height / 2))
            Else
                Height = sPoint2.Y + sSize.Height + (descSize.Height - CInt(Math.Round(sSize.Height / 2))) ' + CInt(Math.Round(sSize.Height / 2))
                sPoint2 = New Point(sPoint2.X, sPoint2.Y + (descSize.Height - CInt(Math.Round(sSize.Height / 2)) - CInt(sSize.Height * 2.5)))
            End If

            'sPoint2 with sub total should be last!
            sPoint2 = New Point(sPoint2.X, sPoint2.Y + sSize.Height * 4)
            'Set cnter
            cnt = i

            'Add pages if total height of print is more than page height (size)
            If cnt < transCount Then
                Dim height2 As Int32() = New Integer() {e.Graphics.MeasureString(tr(i + 1).trDescr, fnt).Height, e.Graphics.MeasureString("PageNum1", fnt).Height}
                If (sPoint2.Y + sSize.Height * 4 + height2(0) + height2(1) * 3 > e.MarginBounds.Height) Then
                    totalPages += 1
                    'Resets point height
                    sPoint2 = New Point(strtPoint.X + e.MarginBounds.Left, strtPoint.Y + e.MarginBounds.Top)
                    'End printing on same page to start a new one
                    cnt = i + 1
                    Exit For
                End If
            End If
        Next

    End Sub
    
    Public Sub Preview()
        PrintPreviewDialog1.Show()
    End Sub
End Class

'Form1
Code: Select all
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim dataLst As List(Of PrintTransactions.TransactionsData) = New List(Of PrintTransactions.TransactionsData)()
        Dim cData As PrintTransactions.TransactionsData

        Dim prData(dataLst.Count - 1) As PrintTransactions.TransactionsData
        For i As Integer = 0 To dataLst.Count - 1
            prData(i) = New PrintTransactions.TransactionsData()
            prData(i) = dataLst.Item(i)
        Next
        'As always, dummy data
        Dim num As Integer = 25 ' Could be any number

        Dim data(num) As PrintTransactions.TransactionsData

        For i As Integer = 0 To num
            data(i) = New PrintTransactions.TransactionsData()
            data(i).trDescr = "Some descr " & i + 1 & ". Any busy" & " Hellos " & "dsadsadadsadadsadsadadsadadsadsadadsadadsadsadadsadadsadsadadsadadsadsadadsada"
            data(i).trDate = #5/11/2013#
            data(i).trValue = 1212.2 + i
        Next

        Dim prnt As PrintTransactions = New PrintTransactions(data) ' Give data array to let class do all other work.
        'Preview, also present and could be called prnt.Print()
        prnt.Preview()

    End Sub
EDIT:
is there a fix for the longest text to split on multi lines?
Code: Select all
            Dim Rectf As RectangleF = New Rectangle(90, 290 + sPoint.Y, descSize.Width - sPoint.X - 45, sSize.Height + 15)
            e.Graphics.DrawString(replaceDesc, fnt, Brushes.Black, Rectf, SF)

'sample
data(i).trDescr = "Some descr " & i + 1 & ". Any busy" & " Hellos " & "dsadsadadsadadsadsadadsadadsadsadadsadadsadsadadsadadsadsadadsadadsadsadadsada" & "'Height = sPoint.Y + sSize.Height + (descSize.Height - CInt(Math.Round(sSize.Height / 2))) ' + CInt(Math.Round(sSize.Height / 2))"
so it will not to be larger then this bar?
Code: Select all
 e.Graphics.FillRectangle(Brushes.DarkGray, New Rectangle(50, Height, e.MarginBounds.Width - sPoint.X - 35, 30))
visit us on:


http://www.softpedia.com/get/System/Lau ... -Run.shtml
Check it out ! http://www.softpedia.com/publisher/I-A- ... 90017.html
Check it out ! http://www.softpedia.com/get/Desktop-En ... lock.shtml
User avatar
CodenStuff
Site Admin
Site Admin
Posts: 4389
Joined: Tue Aug 04, 2009 1:47 am

Re: Help with Print Document
CodenStuff
I found printing to always be a bit of a pain in the bum. However I found it much easier to use a Word document template and populate the bookmarks within that template via code.

If you've never done it before all you do is create a template in Word and create tagged bookmarks within the document where you want certain information to appear. The below link gives an example of how to do this if you're interested in going down this route.

http://www.dreamincode.net/forums/topic ... d-preview/

I used this method when creating my Member Management Database app here:
http://www.codenstuff.com/forum/viewtop ... 70&t=12344
You can see the Word templates in the Members > Printouts folder
Welcome to CodenStuff.com Learn Code, Love Code. Thank you for being a member of the community.
User avatar
Dummy1912
VIP - Donator
VIP - Donator
Posts: 1969
Joined: Sat Aug 21, 2010 2:17 pm

Re: Help with Print Document
Dummy1912
Howdy :D

glad to hear from you once more ;)

uhm okay i will look into it and let you know

and yeah i know print parts are really a pain in our bum hahahaha

:lover;


EDIT:
Uhm i see your MemberManager has no source lol
how do you replace the text in the word file then?
because the link use a Add Reference 'Microsoft Word

Thanks
visit us on:


http://www.softpedia.com/get/System/Lau ... -Run.shtml
Check it out ! http://www.softpedia.com/publisher/I-A- ... 90017.html
Check it out ! http://www.softpedia.com/get/Desktop-En ... lock.shtml
User avatar
CodenStuff
Site Admin
Site Admin
Posts: 4389
Joined: Tue Aug 04, 2009 1:47 am

Re: Help with Print Document
CodenStuff
Yes you need to add a reference to "Microsoft.Office.Interop.Word"

This is the code from the printing form:
Code: Select all
Imports System.IO
Imports Microsoft.Office.Interop

Public Class Printing
    Private Sub Printing_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        ' make a reference to a directory
        Dim di As New IO.DirectoryInfo(Application.StartupPath & "\Members\Printing\")
        Dim diar1 As IO.FileInfo() = di.GetFiles("*.docx", SearchOption.TopDirectoryOnly)

        Dim dra As IO.FileInfo

        'list the names of all files in the specified directory
        For Each dra In diar1
            If Not dra.Name.StartsWith("~$") Then
                If dra.Name.Trim.Length > 2 Then
                    ListBox1.Items.Add(dra.Name)
                End If
            End If
        Next
        Button1.Enabled = False

    End Sub

    Private Sub ListBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ListBox1.SelectedIndexChanged
        Label2.Text = "Checking Template Variables..."
        If TestTemplate(ListBox1.SelectedItem) = True Then
            Label2.Text = "- Template is valid -"
            Button1.Enabled = True
        Else
            Label2.Text = ""
            Button1.Enabled = False
        End If
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Button1.Enabled = False
        Dim wd As Word.Application
        Dim wdDoc As Word.Document

        For Each MB As Member In PrintMembers
            Try
                wd = New Word.Application
                'wd.Visible = True
                wdDoc = wd.Documents.Add(Application.StartupPath & "\Members\Printing\" & ListBox1.SelectedItem) 'Add document to Word
                With wdDoc
                    .FormFields("fullname").Result = MB.Title & " " & MB.Firstname & " " & MB.Surname & vbNewLine
                    .FormFields("address1").Result = MB.Address1 & vbNewLine
                    If MB.Address2.ToString.Length < 2 Then
                        .FormFields("address2").Delete()
                    Else
                        .FormFields("address2").Result = MB.Address2 & vbNewLine
                    End If

                    If MB.Address3.ToString.Length < 2 Then
                        .FormFields("address3").Delete()
                    Else
                        .FormFields("address3").Result = MB.Address3 & vbNewLine
                    End If
                    .FormFields("town").Result = MB.Town & vbNewLine
                    If MB.County.ToString.Length < 2 Then
                        .FormFields("county").Delete()
                    Else
                        .FormFields("county").Result = MB.County & vbNewLine
                    End If
                    .FormFields("postcode").Result = MB.Postcode & vbNewLine
                End With
                wdDoc.SaveAs(Application.StartupPath & "\PFKCMMDoc.doc") 'Saves the Document
                wd.ActiveDocument.PrintOut(
                    Background:=True,
                    Append:=False,
                    Range:=Word.WdPrintOutRange.wdPrintCurrentPage,
                    Item:=Word.WdPrintOutItem.wdPrintDocumentContent,
                    Copies:="1",
                    Pages:="1",
                    PageType:=Word.WdPrintOutPages.wdPrintAllPages,
                    PrintToFile:=False,
                    Collate:=True,
                    ManualDuplexPrint:=False)
                'MsgBox("Please check the folder of employees and open the name of the employee to print his/her document", MsgBoxStyle.OkOnly)
                wd.Application.Quit() 'Closing Word Application
                wd = Nothing 'Releasing References to Variable
                ''''My.Computer.FileSystem.DeleteFile(Application.StartupPath & "\PFKCMMDoc.doc")
                wdDoc = Nothing
            Catch ex As Exception
                MsgBox(ex.Message)
            End Try

        Next
        'RichTextBox1.Text = wdDoc
        MsgBox("Printing completed")
        Me.Close()
    End Sub

    Public Function TestTemplate(ByVal template As String)
        Dim wd As Word.Application
        Dim wdDoc As Word.Document
        Try
            wd = New Word.Application
            'wd.Visible = True
            wdDoc = wd.Documents.Add(Application.StartupPath & "\Members\Printing\" & template) 'Add document to Word
            With wdDoc
                .FormFields("fullname").Result = ""
                .FormFields("address1").Result = ""
                .FormFields("address2").Result = ""
                .FormFields("address3").Result = ""
                .FormFields("town").Result = ""
                .FormFields("county").Result = ""
                .FormFields("postcode").Result = ""
            End With
            wd = Nothing 'Releasing References to Variable
            'My.Computer.FileSystem.DeleteFile("C:\CraigSoftware\tempo.doc")
            wdDoc = Nothing
            Return True
        Catch ex As Exception
            MsgBox("Please ensure the template has the following bookmark variables:" & vbNewLine & vbNewLine & "fullname" & vbNewLine & "address1" & vbNewLine & "address2" & vbNewLine & "address3" & vbNewLine & "town" & vbNewLine & "county" & vbNewLine & "postcode", MsgBoxStyle.Critical, "Template Error")
            Return False
        End Try
    End Function
End Class
You just need to make sure you Word document has the bookmarks you need in it. Example I added a bookmark to the Word document called "fullname" and in the code above you can see I've populated that bookmark with the persons name...ect.

Hope this helps
Welcome to CodenStuff.com Learn Code, Love Code. Thank you for being a member of the community.
User avatar
Dummy1912
VIP - Donator
VIP - Donator
Posts: 1969
Joined: Sat Aug 21, 2010 2:17 pm

Re: Help with Print Document
Dummy1912
Thank you Codenstuff
i will try it out :)
visit us on:


http://www.softpedia.com/get/System/Lau ... -Run.shtml
Check it out ! http://www.softpedia.com/publisher/I-A- ... 90017.html
Check it out ! http://www.softpedia.com/get/Desktop-En ... lock.shtml
5 posts Page 1 of 1
Return to “Coding Help & Support”