StatementTable.vb
''
'' This code is part of Document Solutions for Imaging demos.
'' Copyright (c) MESCIUS inc. All rights reserved.
''
Imports System.Drawing
Imports System.IO
Imports GrapeCity.Documents.Drawing
Imports GrapeCity.Documents.Text
Imports GrapeCity.Documents.Imaging
Imports GrapeCity.Documents.Layout
Imports GCTEXT = GrapeCity.Documents.Text
Imports GCDRAW = GrapeCity.Documents.Drawing

'' This example shows how to use the GrapeCity.Documents.Drawing.TableRenderer
'' class to render a document with a layout typically used in account statements or invoices.
Public Class StatementTable
    Public Function GenerateImage(
        ByVal pixelSize As Size,
        ByVal dpi As Single,
        ByVal opaque As Boolean,
        Optional ByVal sampleParams As String() = Nothing) As GcBitmap

        Dim bmp = New GcBitmap(pixelSize.Width, pixelSize.Height, opaque, dpi, dpi)
        Using g = bmp.CreateGraphics(Color.White)
            DrawTable(g, pixelSize.Width, pixelSize.Height)
        End Using
        Return bmp
    End Function

    Private Class InfoLine
        Public ReadOnly Property Indent As Integer
        Public ReadOnly Property Text As String
        Public ReadOnly Property Sum2021 As Integer
        Public ReadOnly Property Sum2020 As Integer
        Public ReadOnly Property Sum2019 As Integer
        Public ReadOnly Property BoldText As Boolean
        Public ReadOnly Property CaptionOnly As Boolean
        Public ReadOnly Property DrawSign As Boolean
        Public ReadOnly Property ThinLine As Boolean
        Public ReadOnly Property BoldLine As Boolean

        Public Sub New(indent As Integer, text As String, sum2021 As Integer, sum2020 As Integer, sum2019 As Integer,
            Optional boldText As Boolean = False,
            Optional captionOnly As Boolean = False,
            Optional drawSign As Boolean = False,
            Optional thinLine As Boolean = False,
            Optional boldLine As Boolean = False)

            Me.Indent = indent
            Me.Text = text
            Me.Sum2021 = sum2021
            Me.Sum2020 = sum2020
            Me.Sum2019 = sum2019
            Me.BoldText = boldText
            Me.CaptionOnly = captionOnly
            Me.DrawSign = drawSign
            Me.ThinLine = thinLine
            Me.BoldLine = boldLine
        End Sub
    End Class

    Private Shared Sub DrawTable(g As GcGraphics, pageWidth As Integer, pageHeight As Integer)
        Dim items = New InfoLine() {
            New InfoLine(0, "Net sales:", 0, 0, 0, captionOnly:=True),
            New InfoLine(1, "Products", 297392, 220747, 213883, drawSign:=True),
            New InfoLine(1, "Services", 68425, 53768, 46291, thinLine:=True),
            New InfoLine(2, "Total net sales", 365817, 274515, 260174, boldText:=True),
            New InfoLine(0, "Cost of sales:", 0, 0, 0, captionOnly:=True),
            New InfoLine(1, "Products", 192266, 151286, 144996),
            New InfoLine(1, "Services", 20715, 18273, 16786, thinLine:=True),
            New InfoLine(2, "Total cost of sales", 212981, 169559, 161782, boldText:=True, thinLine:=True),
            New InfoLine(3, "Gross margin", 152836, 104956, 98392, boldText:=True, thinLine:=True),
            New InfoLine(0, "Operating expenses:", 0, 0, 0, captionOnly:=True),
            New InfoLine(1, "Research and development", 21914, 18752, 16217),
            New InfoLine(1, "Selling, general and administrative", 21973, 19916, 18245, thinLine:=True),
            New InfoLine(2, "Total operating expenses", 43887, 38668, 34462, boldText:=True, thinLine:=True),
            New InfoLine(0, " ", 0, 0, 0, captionOnly:=True),
            New InfoLine(0, "Operating income", 108949, 66288, 63930),
            New InfoLine(0, "Other income/(expense), net", 258, 803, 1807, thinLine:=True),
            New InfoLine(0, "Income before provision for income taxes", 109207, 67091, 65737, boldText:=True),
            New InfoLine(0, "Provision for income taxes", 14527, 9680, 10481, thinLine:=True),
            New InfoLine(0, "Net income", 94680, 57411, 55256, boldText:=True, drawSign:=True, boldLine:=True)
        }

        Dim host = New LayoutHost()
        Dim view = host.CreateView(pageWidth, pageHeight)

        Dim rt = view.CreateRect()
        '' rt.AnchorTopLeft(Nothing, 30, 50)
        rt.AnchorTopLeft(Nothing, 64, 64)

        Dim ta = New TableRenderer(g,
            rt, FixedTableSides.TopLeft,
            rowCount:=items.Length + 3,
            columnCount:=7,
            gridLineColor:=Color.Transparent,
            gridLineWidth:=0)

        Dim columns = ta.ColumnRects
        columns(0).SetWidth(420)
        columns(1).SetWidth(25)
        columns(2).SetWidth(100)
        columns(3).SetWidth(25)
        columns(4).SetWidth(100)
        columns(5).SetWidth(25)
        columns(6).SetWidth(100)

        Dim fmt = New TextFormat() With
            {
                .Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "FreeMono.ttf")),
                .ForeColor = Color.FromArgb(38, 38, 38),
                .FontSize = 14,
                .FontSizeInGraphicUnits = True
            }
        Dim fmtCaptionBold = New TextFormat(fmt) With
            {
                .FontBold = True,
                .FontSize = 15
            }
        Dim fmtCaptionLight = New TextFormat(fmt) With
            {
                .ForeColor = Color.FromArgb(142, 142, 142),
                .FontSize = 15
            }
        Dim fmtBold = New TextFormat(fmt) With
            {
                .FontBold = True
            }

        Dim csHeader1 = New CellStyle() With
            {
                .TextAlignment = TextAlignment.Center,
                .PaddingBottom = 25,
                .CreateTextLayout = Function(gr As GcGraphics, style As CellStyle, dat As Object)
                                         Dim tl = gr.CreateTextLayout()
                                         tl.AppendLine("ACME Inc." & vbLf & vbLf & "CONSOLIDATED STATEMENTS OF OPERATIONS", fmtCaptionBold)
                                         tl.Append("(in millions, except number of shares which are reflected in thousands and per share amounts)", fmtCaptionLight)
                                         Return tl
                                     End Function
            }
        ta.AddCell(csHeader1, 0, 0, 1, 7, Nothing)

        Dim csThinLine = New CellStyle() With
            {
                .Background = True,
                .Borders = FrameBorders.BottomBorder,
                .LinePaddingBottom = -1,
                .LineWidth = 1
            }
        Dim csBoldLine = New CellStyle(csThinLine) With
            {
                .LinePaddingBottom = -3,
                .LineWidth = 3
            }

        Dim csHeader2 = New CellStyle(csThinLine) With
            {
                .PaddingBottom = 5,
                .TextAlignment = TextAlignment.Center,
                .TextFormat = fmtBold
            }
        ta.AddCell(csHeader2, 1, 1, 1, 6, "Years ended")
        ta.SetHorizontalGridLineWidth(2, 1)

        Dim csHeader3 = New CellStyle() With
            {
                .PaddingTopBottom = 5,
                .TextAlignment = TextAlignment.Center,
                .TextFormat = fmtBold
            }
        ta.AddCell(csHeader3, 2, 1, 1, 2, "September 25," & vbLf & "2021")
        ta.AddCell(csHeader3, 2, 3, 1, 2, "September 26," & vbLf & "2020")
        ta.AddCell(csHeader3, 2, 5, 1, 2, "September 28," & vbLf & "2019")
        ta.AddCell(csThinLine, 2, 1, 1, 6)
        ta.SetHorizontalGridLineWidth(3, 1)

        Dim csText = New CellStyle() With
            {
                .TextFormat = fmt,
                .TextAlignment = TextAlignment.Leading,
                .PaddingTopBottom = 4
            }
        Dim csBoldText = New CellStyle(csText) With
            {
                .TextFormat = fmtBold
            }
        Dim csNum = New CellStyle() With
            {
                .TextFormat = fmt,
                .TextAlignment = TextAlignment.Trailing,
                .PaddingTopBottom = 4,
                .PaddingRight = 10
            }
        Dim csBoldNum = New CellStyle(csNum) With
            {
                .TextFormat = fmtBold
            }
        Dim csBand = New CellStyle() With
            {
                .FillColor = Color.FromArgb(245, 245, 245),
                .Background = True
            }

        For i = 0 To items.Length - 1
            Dim item = items(i)
            Dim rowIndex = i + 3

            If (i And 1) <> 0 Then
                ta.AddCell(csBand, rowIndex, 0, 1, 7)
            End If

            Dim tc = ta.AddCell(If(item.BoldText, csBoldText, csText), rowIndex, 0, item.Text)
            tc.TextLayout.FirstLineIndent = item.Indent * 8 + 10

            Dim csCurrNum = If(item.BoldText, csBoldNum, csNum)
            If item.DrawSign Then
                ta.AddCell(csCurrNum, rowIndex, 1, "$")
                ta.AddCell(csCurrNum, rowIndex, 3, "$")
                ta.AddCell(csCurrNum, rowIndex, 5, "$")
            End If
            If Not item.CaptionOnly Then
                ta.AddCell(csCurrNum, rowIndex, 2, item.Sum2021.ToString("n0"))
                ta.AddCell(csCurrNum, rowIndex, 4, item.Sum2020.ToString("n0"))
                ta.AddCell(csCurrNum, rowIndex, 6, item.Sum2019.ToString("n0"))
            End If

            If item.ThinLine Then
                ta.AddCell(csThinLine, rowIndex, 1, 1, 6)
                ta.SetHorizontalGridLineWidth(rowIndex + 1, 1)
            ElseIf item.BoldLine Then
                ta.AddCell(csBoldLine, rowIndex, 1, 1, 6)
                ta.SetHorizontalGridLineWidth(rowIndex + 1, 3)
            End If
        Next

        ta.Render()
    End Sub
End Class