VB.NET: PrintDocument, Creating/Printing Table with Multiline Cell

I gave you a simple sample in the previous article about how to print in a tabular format.
And now I'll show you how to make it tidier in longer text value.
So, we'll make some value become longer.

Sub Data_Load()
    dt = New DataTable
    With dt.Columns
        .Add("code"Type.GetType("System.String"))
        .Add("name"Type.GetType("System.String"))
        .Add("address"Type.GetType("System.String"))
    End With

    Dim ItemRow As DataRow

    ItemRow = dt.NewRow()
    ItemRow("code") = "A001"
    ItemRow("name") = "Dwi Nuraeni Permata Andikasari"
    ItemRow("address") = "Jl. Linggawastu No.15, Tamansari, " & _
                         "Kec. Bandung Wetan, Kota Bandung, Jawa Barat 40116"
    dt.Rows.Add(ItemRow)

    temRow = dt.NewRow()
    ItemRow("code") = "A002"
    ItemRow("name") = "Kania Desiani Tri Hapsari Ardiana"
    ItemRow("address") = "Jakarta"
    dt.Rows.Add(ItemRow)

    ItemRow = dt.NewRow()
    ItemRow("code") = "A002"
    ItemRow("name") = "Naufal Hartanto"
    ItemRow("address") = "Medan"
    dt.Rows.Add(ItemRow)

End Sub

If we run the program without changing any other code, it will result as below.


Then how to make it tidy? We are still using the same function but we need to modify some code under PrintDocument1_PrintPage event.

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

    'get starting point of y from top margin 
     Dim CurY As Integer = yZero

    'print title only on the first page.
     If iPage = 0 Then
        CurY = pf.PrintCellText("Member Data", CurY, xZero, PWArea, e, pf.FntTitle, pf.MidCenter)
    End If

    'give space between title and table
    CurY = CurY + 10

    'code to handle if more than one page
    If iPage > 0 Then CurY = yZero

    'for saving header text in array
    Dim ColHeader() As String = {"Member Code", "Member Name", "Address"}

    'for saving columns width in array
    'get width with proportional of printing area width
    Dim ColWidth() As Integer = {CInt(PWArea * 0.3), CInt(PWArea * 0.3), CInt(PWArea * 0.4)}

    'starting position of x for each columns
    Dim ColX(ColWidth.Length - 1) As Integer

    'width value that already used in 1 loop
    'for counting starting point on each columns
    Dim totColWidth As Integer = xZero

    'variable to save height of character that printed 
    Dim iResult As Integer

    For i As Integer = 0 To ColWidth.Length - 1
        'counting starting point on each columns
        ColX(i) = totColWidth : totColWidth = totColWidth + ColWidth(i)
        'print table header
        iResult = pf.PrintCellText(ColHeader(i), ColX(i), CurY, ColWidth(i), e, _
                                   pf.FntTableHeader, pf.MidCenter, False)
    Next

    'create rectangles for each cell
    For i As Integer = 0 To ColWidth.Length - 1
        e.Graphics.DrawRectangle(Pens.Black, ColX(i), CurY, ColWidth(i), iResult - CurY)
    Next

    'get y position from the height of last text printed
    CurY = iResult

    Dim iMore As Integer = 0

    Do While r <= dt.Rows.Count - 1
        'print text value each cell
        iResult = pf.PrintCellText(dt.Rows(r)("code"), ColX(0), CurY, ColWidth(0), e, _
                                   pf.FntTableCell, pf.MidLeft, False)
        If iResult > iMore Then iMore = iResult

        iResult = pf.PrintCellText(dt.Rows(r)("name"), ColX(1), CurY, ColWidth(1), e, _
                                   pf.FntTableCell, pf.MidLeft, False)
        If iResult > iMore Then iMore = iResult

        iResult = pf.PrintCellText(dt.Rows(r)("address"), ColX(2), CurY, ColWidth(2), e, _
                                   pf.FntTableCell, pf.MidLeft, False)
        If iResult > iMore Then iMore = iResult
        
       
        'create rectangles for each cell
        For i As Integer = 0 To ColWidth.Length - 1
            e.Graphics.DrawRectangle(Pens.Black, ColX(i), CurY, ColWidth(i), iMore - CurY)
        Next

        'get y position from the height of last text printed 
        CurY = iMore

        'create and go to the next page if already reached 90% height of the printing area.
        If CurY >= 0.9 * PHArea Then
            e.HasMorePages = True
            iPage += 1
            r += 1
            Return
        End If

        r += 1
    Loop

    If r = dt.Rows.Count Then e.HasMorePages = False

End Sub

Complete code as following:



Still using similar UI:


Then start to run and print.






Post a Comment

4 Comments

Daniel said…
Excellent, your code helped me a lot
Unknown said…
Hi, can you help me with this error.

'declaring class printing
"Dim pf As PrintingFormat = New PrintingFormat"

why is that "PrintingFormat" is not recognized? please help what i have to do?
rani said…
PrintingFormat is name of a class that I made before in this below link article:
https://rani-irsan.blogspot.com/2019/10/vbnet-printdocument-printing-in-tabular.html


This article is the next part after.
Putra Bengkulu said…
kalau mau menambahkan total di bawahnya....gimana