GetTablePages.vb
''
'' This code is part of Document Solutions for PDF .NET demos.
'' Copyright (c) MESCIUS inc. All rights reserved.
''
Imports System.IO
Imports System.Drawing
Imports System.Linq
Imports System.Collections.Generic
Imports GrapeCity.Documents.Pdf
Imports GrapeCity.Documents.Pdf.Recognition
Imports GrapeCity.Documents.Text
Imports GrapeCity.Documents.Common
Imports GCTEXT = GrapeCity.Documents.Text

Public Class GetTablePages
    Public Function CreatePDF(ByVal stream As Stream) As Integer
        Const DPI As Single = 72
        Const margin As Single = 36
        Dim doc = New GcPdfDocument()

        Dim tf = New TextFormat() With {
            .Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "NotoSans-Regular.ttf")),
            .FontSize = 9,
            .ForeColor = Color.Black
        }
        Dim tfHdr = New TextFormat(tf) With {
            .Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "NotoSans-Bold.ttf")),
            .FontSize = 11,
            .ForeColor = Color.DarkBlue
        }
        Dim tfRed = New TextFormat(tf) With {.ForeColor = Color.Red}

        Using fs = File.OpenRead(Path.Combine("Resources", "PDFs", "product-list.pdf"))
            Dim page = doc.NewPage()
            page.Landscape = True
            Dim g = page.Graphics

            Dim rc = Util.AddNote(
                "This sample loads a PDF that contains a table split between several pages (a product price list), " &
                "and extracts the tables on all pages using the Page.GetTable() method. " &
                "The extracted data is printed as a list of rows and cells. " &
                "The source product list PDF is appended to the generated document for reference.",
                page,
                New RectangleF(margin, margin, page.Bounds.Width - margin * 2, page.Bounds.Height - margin * 2))

            Dim tl = g.CreateTextLayout()
            tl.MaxWidth = page.Bounds.Width
            tl.MaxHeight = page.Bounds.Height
            tl.MarginAll = margin
            tl.MarginTop = rc.Bottom
            tl.DefaultTabStops = 165

            Dim docSrc = New GcPdfDocument()
            docSrc.Load(fs)

            For i = 0 To docSrc.Pages.Count - 1
                ' TableExtractOptions allow you to fine-tune table recognition accounting for
                ' specifics of the table formatting:
                Dim teo = New TableExtractOptions()
                Dim GetMinimumDistanceBetweenRows = teo.GetMinimumDistanceBetweenRows
                ' In this particular case, we slightly increase the minimum distance between rows
                ' to make sure cells with wrapped text are not mistaken for two cells:
                teo.GetMinimumDistanceBetweenRows = Function(list)
                                                        Dim res = GetMinimumDistanceBetweenRows(list)
                                                        Return res * 1.2F
                                                    End Function
                Dim top = If(i = 0, DPI * 2, DPI)
                ' Get the table at the specified bounds:
                Dim itable = docSrc.Pages(i).GetTable(New RectangleF(DPI * 0.25F, top, DPI * 8, DPI * 10.5F - top), teo)

                ' Add table data to the text layout:
                tl.Append($"{vbLf}Table on page {i + 1} of the source document has {itable.Cols.Count} column(s) and {itable.Rows.Count} row(s), table data is:", tfHdr)
                tl.AppendParagraphBreak()
                For row = 0 To itable.Rows.Count - 1
                    Dim tfmt = If(row = 0, tfHdr, tf)
                    For col = 0 To itable.Cols.Count - 1
                        Dim cell = itable.GetCell(row, col)
                        If col > 0 Then
                            tl.Append(vbTab, tfmt)
                        End If
                        If cell Is Nothing Then
                            tl.Append("<no cell>", tfRed)
                        Else
                            tl.Append(cell.Text, tfmt)
                        End If
                    Next
                    tl.AppendLine()
                Next
            Next

            ' Print the extracted data:
            Dim to_ = New TextSplitOptions(tl) With {.RestMarginTop = margin, .MinLinesInFirstParagraph = 2, .MinLinesInLastParagraph = 2}
            tl.PerformLayout(True)
            While True
                Dim rest As TextLayout = Nothing
                Dim splitResult = tl.Split(to_, rest)
                doc.Pages.Last.Graphics.DrawTextLayout(tl, PointF.Empty)
                If splitResult <> SplitResult.Split Then
                    Exit While
                End If
                tl = rest
                doc.NewPage().Landscape = True
            End While

            ' Append the original document for reference:
            doc.MergeWithDocument(docSrc)

            doc.Save(stream)
            Return doc.Pages.Count
        End Using
    End Function
End Class