Jumat, 21 Agustus 2020

Vb.Net : Printdocument, Printing In Tabular Format

Hi guys, this article contains a sample on how to make a table using PrintDocument for printing. Something like this: It will be easier to understand if you read previous articles. Introducing PrintDocument Component Setting Font for PrintDocument Printing Setting Vertical (Y) Position Automatically on PrintDocument Setting Alignment We're getting to an intermediate level. Let's modify PrintCellText Function into the following code: Public Function PrintCellText( ByVal strValue As String ,  ByVal  x As Integer , _                                ByVal  y As Integer ,  ByVal  w As Integer , _                                ByVal  e As  System.Drawing.Printing.PrintPageEventArgs, _                               Font As Font , Format As StringFormat , _                               Optional Border As Boolean = False , _                                Optional  Fill As Brush = Nothing , _                                Optional  h As Integer = 0) As Integer      Dim cellRect As RectangleF = New RectangleF ()     cellRect.Location = New Point (x, y)      If h > 0 Then          cellRect.Size = New Size (w, h)      Else         cellRect.Size = New Size (w, 10 +                              ( CInt (e.Graphics.MeasureString(strValue, Font, w - 10,                               StringFormat .GenericTypographic).Height)))      End If      If IsNothing(Fill) = False Then          e.Graphics.FillRectangle(Fill, Rectangle .Round(cellRect))      End If     e.Graphics.DrawString(strValue, Font, Brushes .Black, cellRect, Format)      If  Border = True Then          e.Graphics.DrawRectangle(Pens.Black, Rectangle .Round(cellRect))      Else          e.Graphics.DrawRectangle(Pens.Transparent, Rectangle .Round(cellRect))      End If      Return y + cellRect.Size.Height End Function See the highlighted text for detail of changes. I also add 3 optional parameters. Border, fill (for fill color), and h for the height that manually set. Next, we're going to tidy up the code into a class file. We're still using our previous project. Add a class by selecting menu Project -> Add Class... Name it with PrintingFormat, then click Add. This code is written in the class, you may copy it. But hopefully, you try to understand each code in it. Imports System.Drawing.Printing Public Class PrintingFormat Private mTopLeft As StringFormat = New StringFormat() Private mTopCenter As StringFormat = New StringFormat() Private mTopRight As StringFormat = New StringFormat() Private mMidLeft As StringFormat = New StringFormat() Private mMidCenter As StringFormat = New StringFormat() Private mMidRight As StringFormat = New StringFormat() Private mBotLeft As StringFormat = New StringFormat() Private mBotCenter As StringFormat = New StringFormat() Private mBotRight As StringFormat = New StringFormat() Public ReadOnly Property FntTitle() As Font Get Return New Font("Arial", 12, FontStyle.Bold, GraphicsUnit.Point) End Get End Property Public ReadOnly Property FntTableHeader() As Font Get Return New Font("Arial", 10, FontStyle.Bold, GraphicsUnit.Point) End Get End Property Public ReadOnly Property FntTableCell() As Font Get Return New Font("Arial", 10, FontStyle.Regular, GraphicsUnit.Point) End Get End Property Public ReadOnly Property TopLeft As StringFormat Get mTopLeft.LineAlignment = StringAlignment.Near mTopLeft.Alignment = StringAlignment.Near Return mTopLeft End Get End Property Public ReadOnly Property TopCenter As StringFormat Get mTopCenter.LineAlignment = StringAlignment.Near mTopCenter.Alignment = StringAlignment.Center Return mTopCenter End Get End Property Public ReadOnly Property TopRight As StringFormat Get mTopRight.LineAlignment = StringAlignment.Near mTopRight.Alignment = StringAlignment.Far Return mTopRight End Get End Property Public ReadOnly Property MidLeft As StringFormat Get mMidLeft.LineAlignment = StringAlignment.Center mMidLeft.Alignment = StringAlignment.Near Return mMidLeft End Get End Property Public ReadOnly Property MidCenter As StringFormat Get mMidCenter.LineAlignment = StringAlignment.Center mMidCenter.Alignment = StringAlignment.Center Return mMidCenter End Get End Property Public ReadOnly Property MidRight As StringFormat Get mMidRight.LineAlignment = StringAlignment.Center mMidRight.Alignment = StringAlignment.Far Return mMidRight End Get End Property Public ReadOnly Property BotLeft As StringFormat Get mBotLeft.LineAlignment = StringAlignment.Far mBotLeft.Alignment = StringAlignment.Near Return mBotLeft End Get End Property Public ReadOnly Property BotCenter As StringFormat Get mBotCenter.LineAlignment = StringAlignment.Far mBotCenter.Alignment = StringAlignment.Center Return mBotCenter End Get End Property Public ReadOnly Property BotRight As StringFormat Get mBotRight.LineAlignment = StringAlignment.Far mBotRight.Alignment = StringAlignment.Far Return mBotRight End Get End Property Public Function PrintCellText(ByVal strValue As String, ByVal x As Integer, ByVal y As Integer, ByVal w As Integer, ByVal e As System.Drawing.Printing.PrintPageEventArgs, Font As Font, Format As StringFormat, Optional ByVal Border As Boolean = False, Optional Fill As Brush = Nothing, Optional h As Integer = 0) As Integer Dim cellRect As RectangleF = New RectangleF() cellRect.Location = New Point(x, y) If h > 0 Then cellRect.Size = New Size(w, h) Else cellRect.Size = New Size(w, 10 + (CInt(e.Graphics.MeasureString(strValue, Font, w - 10, StringFormat.GenericTypographic).Height))) End If If IsNothing(Fill) = False Then e.Graphics.FillRectangle(Fill, Rectangle.Round(cellRect)) End If e.Graphics.DrawString(strValue, Font, Brushes.Black, cellRect, Format) If Border = True Then e.Graphics.DrawRectangle(Pens.Black, Rectangle.Round(cellRect)) Else e.Graphics.DrawRectangle(Pens.Transparent, Rectangle.Round(cellRect)) End If Return y + cellRect.Size.Height End Function End Class You can also download PrintingFormat Class  here. In this class, I only put 3 type of font to be used. FntTitle untuk judul FntTableHeader untuk header tabel FntTableCell untuk isi cell You can add your own font type if needed. Then for UI still using this following: For example, printing data that contain in DataTable. In this case, I'll manually add ItemRow into DataTable. I use DataTable so you can adjust into your own project using any database. I assume that you've already familiar with database programming. Especially fill data into DataTable. Dim dt As DataTable 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"     ItemRow( "address" ) = "Bandung"     dt.Rows.Add(ItemRow)     ItemRow = dt.NewRow()     ItemRow( "code" ) = "A002"     ItemRow( "name" ) = "Kania Desiani"     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 Call sub procedure in form_load event. Private Sub Form1_Load(sender As Object , e As EventArgs ) Handles MyBase.Load     Data_Load() End Sub We'll also declare some variable that used for this printing process. 'declaring class printing   Dim pf As PrintingFormat = New PrintingFormat 'declaring veriable for default  setting     Dim PS As System.Drawing.Printing . PageSettings   Dim  PWArea  As  Integer   Dim  PHArea  As  Integer   Dim  xZero  As  Integer   Dim  yZero  As  Integer   Dim  iPage  As  Integer   Dim  r  As Integer   'variable for saving row number The values of those variables will be set on print_begin event. Private Sub PrintDocument1_BeginPrint(sender As Object , e As PrintEventArgs ) _     Handles PrintDocument1.BeginPrint     PS = PrintDocument1.DefaultPageSettings 'get default  setting       PWArea = PS.PaperSize.Width - (PS.Margins.Left + PS.Margins.Right)     PHArea = PS.PaperSize.Height - (PS.Margins.Left + PS.Margins.Right)     xZero = PS.Margins.Left     yZero = PS.Margins.Top     iPage = 0 'indicate page number      r = 0   End Sub Last in PrintDocument1_PrintPage event. I put comment in code for its descriptions. (green colored) 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         ' ounting 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, True )     Next     'get y position from the height of last text printed      CurY = iResult          Do While r         'print text value each cell         iResult = pf.PrintCellText(dt.Rows(r)( "code" ), ColX(0), CurY, ColWidth(0), e, _                   pf.FntTableCell, pf.MidLeft,  True )         iResult = pf.PrintCellText(dt.Rows(r)( "name" ), ColX(1), CurY, ColWidth(1), e, _                   pf.FntTableCell, pf.MidLeft,  True )         iResult = pf.PrintCellText(dt.Rows(r)( "address" ), ColX(2), CurY, ColWidth(2), e, _                   pf.FntTableCell, pf.MidLeft,  True )           'get y position from the height of last text printed          CurY = iResult         'create and go to the next page if already reached 90% height of 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 Don't forget to add "Imports System.Drawing.Printing", and this below is the complete code: Imports System.Drawing.Printing Public Class Form1 Dim dt As DataTable 'declaring class printing Dim pf As PrintingFormat = New PrintingFormat 'declaring veriable for default setting Dim PS As System.Drawing.Printing.PageSettings Dim PWArea As Integer Dim PHArea As Integer Dim xZero As Integer Dim yZero As Integer Dim iPage As Integer Dim r As Integer 'variable for saving row number 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" ItemRow("address") = "Bandung" dt.Rows.Add(ItemRow) ItemRow = dt.NewRow() ItemRow("code") = "A002" ItemRow("name") = "Kania Desiani" 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 Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Data_Load() End Sub Private Sub Button1_Click(sender As Object, e As EventArgs) _ Handles Button1.Click PrintDocument1.Print() End Sub Private Sub PrintDocument1_BeginPrint(sender As Object, e As PrintEventArgs) Handles PrintDocument1.BeginPrint PS = PrintDocument1.DefaultPageSettings 'get default setting PWArea = PS.PaperSize.Width - (PS.Margins.Left + PS.Margins.Right) PHArea = PS.PaperSize.Height - (PS.Margins.Left + PS.Margins.Right) xZero = PS.Margins.Left yZero = PS.Margins.Top iPage = 0 'indicate page number End Sub 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 'ounting 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, True) Next 'get y position from the height of last text printed CurY = iResult Do While r To make it works with multiline text in cell, read also this article: PrintDocument, Creating/Printing Table with Multiline Cell
Sumber http://rani-irsan.blogspot.com


EmoticonEmoticon