''
'' 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