Results 1 to 14 of 14

Thread: Printing with PrintDocument [Resolve]

  1. #1

    Thread Starter
    Registered User
    Join Date
    Apr 2003
    Location
    Klang, Selangor, Malaysia
    Posts
    163

    Question Printing with PrintDocument [Resolve]

    I had added a PrintDocument to my Project to print something on A4 paper.

    This is the code:
    Code:
    Private Sub PrintDocument_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument.PrintPage
            Dim intY As Integer = 158 
    
            'Print cash
            e.Graphics.DrawString("/", New Font("Courier New", 10, FontStyle.Bold), Brushes.Black, 165, intY - 20)
    
            'Print cheque
            e.Graphics.DrawString("/", New Font("Courier New", 10, FontStyle.Bold), Brushes.Black, 165, intY)
    
            'Print cheque number
            e.Graphics.DrawString("123456", New Font("Courier New", 12, FontStyle.Bold), Brushes.Black, 315, intY - 4)
    
            'Print amount
            e.Graphics.DrawString("12345.00", New Font("Courier New", 12, FontStyle.Bold), Brushes.Black, 440, intY)
    
            'Print number of employees
            e.Graphics.DrawString("123", New Font("Courier New", 12, FontStyle.Bold), Brushes.Black, 580, intY)
        End Sub
    Using the above codes, it will print everything on 1 piece of A4 paper on the specific (x, y) coordinate.

    My question is, if i have very very long information to be printed, and requires it to be printed on 2nd, 3rd, 4th, 5th pages and etc... How should i specific its (x, y) coordinate?

    Please guide me, thank you!
    Last edited by albertlse; Aug 25th, 2003 at 04:03 AM.

  2. #2
    I wonder how many charact
    Join Date
    Feb 2001
    Location
    Savage, MN, USA
    Posts
    3,704
    What you need to is get the textheight of the font... increment a counter by that amount for every line.. if that amount is greater than the height of the paper... you need to NewPage...

    somethin akin to:
    VB Code:
    1. 'myYoffset being the next Y coordinate to move to...
    2. 'g being a graphics object, f being the Font
    3. stringSize = g.MeasureString("TEST", f)
    4.  
    5.  
    6. myYoffset = Convert.ToSingle(stringSize.Height * 1.5)
    'multiplied by 1.5 to give more space between the lines, you can use whatever amount of space you want

    When you move to a new page, reset myYOffset to Y coordinate you want to begin printing the lines...

  3. #3

    Thread Starter
    Registered User
    Join Date
    Apr 2003
    Location
    Klang, Selangor, Malaysia
    Posts
    163
    can you pls explain clearer?
    FYI, the text that i would like to print is here and there, now specific every row follow by another row...

  4. #4
    I wonder how many charact
    Join Date
    Feb 2001
    Location
    Savage, MN, USA
    Posts
    3,704
    I don't understand how much clearer i can be...post a pic of what you want to do...

    For different font sizes, you need to measure the fontsize of every font you use... add it to sum... when the sum is greater than the alloted space... NEWPAGE.

  5. #5

    Thread Starter
    Registered User
    Join Date
    Apr 2003
    Location
    Klang, Selangor, Malaysia
    Posts
    163
    Attached is a picture of the form that I want to print to.
    Refering to the picture of the form, at the center of the form there are 20 rows to be filled up.
    I use this code to fill up 20 row into 1 form:
    Code:
    Private Sub PrintDocument_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument.PrintPage
            Dim intY As Integer = 158
    
            'Print cash
            e.Graphics.DrawString("/", New Font("Courier New", 10, FontStyle.Bold), Brushes.Black, 165, intY - 20)
    
            'Print cheque
            e.Graphics.DrawString("/", New Font("Courier New", 10, FontStyle.Bold), Brushes.Black, 165, intY)
    
            'Print cheque number
            e.Graphics.DrawString("123456", New Font("Courier New", 12, FontStyle.Bold), Brushes.Black, 315, intY - 4)
    
            'Print amount
            e.Graphics.DrawString("12345.00", New Font("Courier New", 12, FontStyle.Bold), Brushes.Black, 440, intY)
    
            'Print number of employees
            e.Graphics.DrawString("123", New Font("Courier New", 12, FontStyle.Bold), Brushes.Black, 580, intY)
    
            'Print 20 records in 1 form
            intY = 450
            Dim intRow As Integer
            For intRow = 0 To 19
            'Print IC
            e.Graphics.DrawString("111111223333", New Font("Courier New", 12, FontStyle.Bold), Brushes.Black, 18, intY)
    
            ''Print SOCSO Number
            e.Graphics.DrawString("S12345678", New Font("Courier New", 12, FontStyle.Bold), Brushes.Black, 160, intY)
    
            ''Print Cross
            e.Graphics.DrawString("X", New Font("Courier New", 12, FontStyle.Bold), Brushes.Black, 270, intY)
    
            ''Print Name
            e.Graphics.DrawString("NAME NAME NAME", New Font("Courier New", 12, FontStyle.Bold), Brushes.Black, 300, intY)
    
            ''Print Amount
            e.Graphics.DrawString("1", New Font("Courier New", 12, FontStyle.Bold), Brushes.Black, 685, intY - 1)
            e.Graphics.DrawString("2", New Font("Courier New", 12, FontStyle.Bold), Brushes.Black, 710, intY - 1)
            e.Graphics.DrawString("5", New Font("Courier New", 12, FontStyle.Bold), Brushes.Black, 740, intY - 1)
            e.Graphics.DrawString("7", New Font("Courier New", 12, FontStyle.Bold), Brushes.Black, 765, intY - 1)
    
            intY += 25
            Next
    
            intY = 955
            'Print Sub-Total Amount
            e.Graphics.DrawString("4", New Font("Courier New", 12, FontStyle.Bold), Brushes.Black, 635, intY)
            e.Graphics.DrawString("4", New Font("Courier New", 12, FontStyle.Bold), Brushes.Black, 660, intY)
            e.Graphics.DrawString("4", New Font("Courier New", 12, FontStyle.Bold), Brushes.Black, 685, intY)
            e.Graphics.DrawString("4", New Font("Courier New", 12, FontStyle.Bold), Brushes.Black, 710, intY)
            e.Graphics.DrawString("4", New Font("Courier New", 12, FontStyle.Bold), Brushes.Black, 740, intY)
            e.Graphics.DrawString("4", New Font("Courier New", 12, FontStyle.Bold), Brushes.Black, 765, intY)
    
            intY = 1000
            'Print Grand Total Amount
            e.Graphics.DrawString("3", New Font("Courier New", 12, FontStyle.Bold), Brushes.Black, 610, intY)
            e.Graphics.DrawString("3", New Font("Courier New", 12, FontStyle.Bold), Brushes.Black, 635, intY)
            e.Graphics.DrawString("3", New Font("Courier New", 12, FontStyle.Bold), Brushes.Black, 660, intY)
            e.Graphics.DrawString("3", New Font("Courier New", 12, FontStyle.Bold), Brushes.Black, 685, intY)
            e.Graphics.DrawString("3", New Font("Courier New", 12, FontStyle.Bold), Brushes.Black, 710, intY)
            e.Graphics.DrawString("3", New Font("Courier New", 12, FontStyle.Bold), Brushes.Black, 740, intY)
            e.Graphics.DrawString("3", New Font("Courier New", 12, FontStyle.Bold), Brushes.Black, 765, intY)
        End Sub
    if i have more than 20 records to be filled into the form, i sure need to print more than 1 form right? clear?

    so how to code it to print it on new page?

    pls guide, thank you.
    Attached Images Attached Images  

  6. #6
    I wonder how many charact
    Join Date
    Feb 2001
    Location
    Savage, MN, USA
    Posts
    3,704
    Ok...

    I want to tell you a somewhat better way to do this...

    Again, you are printing rows... you will need to check the fontsize of each row... and when the sum of the sizes is greater than the space alloted, you start a new page.

    The only thing you need to worry about is if you have to print more than 20 records on a form, its the only thing that will force a new page. So you must only allow 20 records per page.. obvious enough.

    Take a look at a sub i wrote for a program below:

    VB Code:
    1. Private Sub DrawItems(ByRef g As Graphics, ByRef b As Brush, ByRef f As Font, _
    2.     ByRef yourItems As ItemCollection, [b]ByVal x As Integer, _
    3.  ByVal y As Integer, ByVal [width] As Integer, ByVal [height] As Integer[/b])

    Note the bold part of the sub header. I am actually defining a rectangle that encompasses the surface area that holds the records. (see image link here)

    The yellow outline is the rectangle that defines the area. No record can print outside that area, because if the sum of the row heights becomes greater than that area, I force a new page to be printed, but before doing, i remove all the records from the collection that have been printed.

    So when the next page prints, the remaining records are printed.

    Now...
    here's some other code to help you out:
    when you do a graphics.DrawString(), you can also pass a rectangle that defines the area that can be drawn to.

    for example, g.drawString(myrecord, myFont, myBrush, myRectangle)

    In the case of your form, you will take the rectangle that encompasses the whole row area (yellow outline), and divide its height by 20, but keeping its width the same. You assign that to a new rectangle, and you use that rectangle to draw each record.(indicated by the red rectangles in the image link i posted).
    Last edited by nemaroller; Aug 21st, 2003 at 09:37 PM.

  7. #7

    Thread Starter
    Registered User
    Join Date
    Apr 2003
    Location
    Klang, Selangor, Malaysia
    Posts
    163
    thanx for ur explanation!

    if u don't mind, can u make an example of the full code for me to refer? i have no idea of doing it. coz i'm still new. i need more code reference?

    i would appreciate your help. thank you.

  8. #8
    I wonder how many charact
    Join Date
    Feb 2001
    Location
    Savage, MN, USA
    Posts
    3,704
    I whip something together for you in two days...
    But in the meantime...

    1) Do you need to print anything on the form besides the 20 records?

    2) What objects hold your records...? Are they collections of a class you wrote, or datasets?

    3) Can one record span two vertical lines on the form? (for example, can one record take two lines, only allowing 18 more records on the form?... OR are they all limited to one line?)

  9. #9

    Thread Starter
    Registered User
    Join Date
    Apr 2003
    Location
    Klang, Selangor, Malaysia
    Posts
    163
    i'm so glad that u would help me do the coding.

    other then the 20 rows of records,
    i need to print the name & address (as you can see on the picture form) on every page of forms.

    i need to print the sub-total of salary for every page of forms.

    i need to print the grand total of salary on the last page of forms only, not every page...

    i wish to put exactly 1 record in each row. no spanning is allow.

    actually i still havent design wat object should holds my records. but the data is from database. so you think which design is suitable? a dataset? or datagrid? pls suggest...

    all the x and y coordinates i use in the code (which can b seen in my first posting) is exactly where the text whould be printed. you may use that for reference if you need.

    hope my explanation is clear to you. feel free to ask me if anything confuse you.

    hope to get the good news (the coding i mean) from you very soon after 2 days!!!

  10. #10
    I wonder how many charact
    Join Date
    Feb 2001
    Location
    Savage, MN, USA
    Posts
    3,704
    actually i still havent design wat object should holds my records. but the data is from database. so you think which design is suitable? a dataset? or datagrid? pls suggest...

    Well... a dataset probably. I don't know what other requirements you have for your program... if you need to translate the data before printing, or do other evaluations, you might be better off grabbing the data from the database and creating objects that represent that data, and putting those objects into a collection.

    If you don't have those requirements, then its a waste of resources and time required to design the classes.

    So you decide and be sure to get back to me..

    Btw, should the FINAL TOTAL be printed in the rows section ? Or printed beneath it? or above it?

  11. #11

    Thread Starter
    Registered User
    Join Date
    Apr 2003
    Location
    Klang, Selangor, Malaysia
    Posts
    163
    actually the 20 records should be retrieve from database data.
    but for testing now, just use text only, is it possible?
    just try it in simple way.
    actually every row of records contains name, NRIC, membership a/c number and salary.
    the "sub-total" is the total of salary in each page. it should appears at the bottom, after the 20 records.
    whereas, the "grand-total" is the total of all sub-total of all pages. it should appears at the bottom of "sub-total", but only appears once, which is at the last page only.
    hope my information is clear enough. feel free to ask me if any confuse. thank you.

  12. #12
    I wonder how many charact
    Join Date
    Feb 2001
    Location
    Savage, MN, USA
    Posts
    3,704
    Ok, forgot about this, sorry...

    Anyway, here's what I whipped together...

    VB Code:
    1. Imports System.Drawing.Printing
    2. Imports System.Text
    3.  
    4. Public Class Form1
    5.     Inherits System.Windows.Forms.Form
    6.  
    7.     Private Structure EmployeeData
    8.         Dim EmployeeName As String
    9.         Dim NRIC As String
    10.         Dim AccountNumber As String
    11.         Dim Salary As String
    12.     End Structure
    13.     Private myCollection As New Collection()
    14.     Private subtotals As Decimal = 0
    15.     Private pagetotal As Decimal = 0
    16. [+Windows Designer Generated Code]
    17.  
    18.  
    19.     Private Sub Button1_Click(ByVal sender As System.Object, _
    20.      ByVal e As System.EventArgs) Handles Button1.Click
    21.         'setup a collection representing some test values
    22.         Dim myEmployeedata As EmployeeData
    23.         myEmployeedata.AccountNumber = "1232322"
    24.         myEmployeedata.EmployeeName = "Thai Xung"
    25.         myEmployeedata.NRIC = "???"
    26.         myEmployeedata.Salary = "1232.23"
    27.         Dim i As Integer
    28.         For i = 0 To 23
    29.             myCollection.Add(myEmployeedata)
    30.         Next
    31.         myEmployeedata.AccountNumber = "999999999"
    32.         myEmployeedata.EmployeeName = "Hu Vouh"
    33.         myEmployeedata.NRIC = "XX"
    34.         myEmployeedata.Salary = "5232.23"
    35.  
    36.         myCollection.Add(myEmployeedata)
    37.  
    38.         'signal to print
    39.         OutputData()
    40.     End Sub
    41.  
    42.     Private Sub OutputData()
    43.  
    44.         Dim printdoc As PrintDocument = New PrintDocument()
    45.         AddHandler printdoc.PrintPage, AddressOf printdoc_printpage
    46.  
    47.  
    48.  
    49.         Dim dlgPrintPreview As PrintPreviewDialog = New PrintPreviewDialog()
    50.         ' Set any optional properties of dlgPrintPreview here...
    51.         dlgPrintPreview.Size = New Size(700, 700)
    52.  
    53.  
    54.         dlgPrintPreview.Document = printdoc
    55.  
    56.         dlgPrintPreview.ShowDialog()
    57.  
    58.     End Sub
    59.     Private Shadows Sub printdoc_printpage(ByVal sender As Object, _
    60.      ByVal pEvents As PrintPageEventArgs)
    61.         pEvents.Graphics.PageUnit = GraphicsUnit.Pixel
    62.  
    63.         Dim AddressFont As New Font("Courier New", 12, FontStyle.Bold, GraphicsUnit.Point)
    64.         Dim RowFont As New Font("Courier New", 8, FontStyle.Bold, GraphicsUnit.Point)
    65.         Dim defaultBrush As New SolidBrush(Color.Black)
    66.  
    67.         Dim pageboundaries As RectangleF = New RectangleF(pEvents.PageBounds.X, _
    68.          pEvents.PageBounds.Y, pEvents.PageBounds.Width, pEvents.PageBounds.Height)
    69.  
    70.  
    71.         'call function to draw name and address
    72.  
    73.         DrawNameAndAddress(pEvents.Graphics, AddressFont, defaultBrush, "Name and Address", _
    74.            New RectangleF(pageboundaries.X, pageboundaries.Y, _
    75.             pageboundaries.Width * 0.4, pageboundaries.Height * 0.2))
    76.  
    77.         'call function to draw the rows of data
    78.         pagetotal = DrawRowData(pEvents, RowFont, defaultBrush, New RectangleF(0, _
    79.            pageboundaries.Height * 0.25, pageboundaries.Width, _
    80.              pageboundaries.Height * 0.7), myCollection)
    81.  
    82.  
    83.  
    84.  
    85.         'draw the salary total for this page
    86.         drawtotals(pagetotal, pEvents.Graphics, AddressFont, defaultBrush, _
    87.         New PointF(500, 500))
    88.  
    89.  
    90.         'adds totals of salaries for that page to the grand total
    91.         subtotals += pagetotal
    92.  
    93.         If pEvents.HasMorePages = False Then
    94.             drawtotals(subtotals, pEvents.Graphics, AddressFont, defaultBrush, _
    95.              New PointF(0, pageboundaries.Height - pageboundaries.Height * 0.05))
    96.  
    97.         End If
    98.         AddressFont.Dispose()
    99.         RowFont.Dispose()
    100.         defaultBrush.Dispose()
    101.         'reset pagetotal
    102.         pagetotal = 0
    103.  
    104.     End Sub
    105.     Private Function DrawRowData(ByRef ev As PrintPageEventArgs, ByRef f As Font, _
    106.     ByRef b As Brush, ByVal lrect As RectangleF, _
    107.     ByVal lData As Collection) As Decimal
    108.  
    109.         'from the rectangleF passed , we need to take its height, and / it by 20,
    110.         'so we have 20 smaller rectangles that fit within the height of the rectangle passed
    111.         Dim g As Graphics = ev.Graphics
    112.  
    113.         Dim rowRectangle As New RectangleF(lrect.X, lrect.Y, lrect.Width, lrect.Height * 0.05)
    114.  
    115.         'rowRectangle represents on row of data
    116.         'but we also need to divide that row into columns
    117.         'to represent the four items we print on each row:
    118.         'Name, NRIC, Account number, salary
    119.         Dim subRectangle As New RectangleF(rowRectangle.X, _
    120.          rowRectangle.Y, rowRectangle.Width * 0.25, rowRectangle.Height)
    121.  
    122.  
    123.  
    124.  
    125.         'We need to define a variable that will keep track
    126.         'of what Y position to print the next line at
    127.         Dim Yoffset As Integer = rowRectangle.Height
    128.  
    129.         ''''''this declaration to help Ctype from the collection
    130.         Dim myemployee As EmployeeData
    131.         ''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    132.  
    133.  
    134.         Dim salarytotals As Decimal = 0
    135.         Dim i As Integer
    136.         Do Until myCollection.Count = 0 OrElse i > 20
    137.             i = i + 1
    138.             myemployee = CType(myCollection(1), EmployeeData)
    139.             g.DrawString(myemployee.EmployeeName, f, b, subRectangle)
    140.             subRectangle.Offset(subRectangle.Width, 0)
    141.             g.DrawString(myemployee.NRIC, f, b, subRectangle)
    142.             subRectangle.Offset(subRectangle.Width, 0)
    143.             g.DrawString(myemployee.AccountNumber, f, b, subRectangle)
    144.             subRectangle.Offset(subRectangle.Width, 0)
    145.             g.DrawString(myemployee.Salary, f, b, subRectangle)
    146.  
    147.  
    148.             'add salary to subtotal
    149.             salarytotals += Convert.ToDecimal(myemployee.Salary)
    150.  
    151.             'remove the item from the collection
    152.             myCollection.Remove(1)
    153.  
    154.             'move to next row
    155.             subRectangle.X = rowRectangle.X 'CR
    156.             subRectangle.Offset(0, Yoffset) 'LF
    157.  
    158.         Loop
    159.  
    160.         'release reference to the passed eventargs.graphics object
    161.         g.Dispose()
    162.         'if more data to print, signal the delegate
    163.         If myCollection.Count > 0 Then
    164.             ev.HasMorePages = True
    165.         Else
    166.             ev.HasMorePages = False
    167.         End If
    168.         Return salarytotals
    169.     End Function
    170.  
    171.     Private Sub DrawNameAndAddress(ByRef g As Graphics, ByRef f As Font, _
    172.      ByRef b As Brush, ByVal s As String, ByVal lRect As RectangleF)
    173.         '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    174.         'normally we would pass a structured string into this function,
    175.         'for this sample project, we build it within this function
    176.         'create a structured string (string with carriage returns)
    177.         Dim sb As New StringBuilder()
    178.         Dim CR() As Char = {Chr(13), Chr(10)}
    179.         sb.Append("Boon Boon Trading Company")
    180.         sb.Append(CR)
    181.         sb.Append("N0 80 JALAN BUNDA RAYA")
    182.         sb.Append(CR)
    183.         sb.Append("75100 MELAKA")
    184.         sb.Append(CR)
    185.         ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    186.         'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    187.         ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    188.         'StringFormat class allows us to wrap text within confines of
    189.         'a rectangle.. this is helpful in case the text on a line exceeds
    190.         'the width alloted on a single line for this text area (Name and Address).
    191.         Dim strFormat As New StringFormat()
    192.         strFormat.Alignment = StringAlignment.Near
    193.         strFormat.LineAlignment = StringAlignment.Near
    194.         strFormat.Trimming = StringTrimming.Word
    195.  
    196.         '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    197.         'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    198.         '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    199.         'draw the information to the page
    200.         g.DrawString(sb.ToString, f, b, lRect, strFormat)
    201.         '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    202.  
    203.     End Sub
    204.     Private Sub drawtotals(ByVal lTotal As Decimal, ByRef g As Graphics, _
    205.      ByRef f As Font, ByRef b As Brush, ByVal lPointF As PointF)
    206.         'Draw the totals of all salaries on the last page
    207.         'g.DrawString("hi", f, b, lPointF.X, lPointF.Y)
    208.     End Sub
    209.  
    210. End Class

  13. #13
    I wonder how many charact
    Join Date
    Feb 2001
    Location
    Savage, MN, USA
    Posts
    3,704
    Now of course, I wouldn't recommend using my code as listed..
    its crude!

    But you can see that I remove an item from the collection of data after its printed, and if there are more items than can be printed ona page, I interupt the loops printing the items, and do a next page, and then continue...

  14. #14

    Thread Starter
    Registered User
    Join Date
    Apr 2003
    Location
    Klang, Selangor, Malaysia
    Posts
    163
    it's working fine now. thanks
    Last edited by albertlse; Aug 25th, 2003 at 04:02 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width