'''' This code is part of Document Solutions for PDF .NET demos.'' Copyright (c) MESCIUS inc. All rights reserved.''ImportsSystem.IOImportsSystem.DrawingImportsSystem.LinqImportsSystem.Collections.GenericImportsGrapeCity.Documents.PdfImportsGrapeCity.Documents.TextImportsGrapeCity.Documents.Pdf.TextMapImportsGrapeCity.Documents.Pdf.StructureImportsGrapeCity.Documents.Pdf.Recognition.StructureImports GCTEXT = GrapeCity.Documents.Text '' Find tables and read their data using structure tags.PublicClassReadTagsTableDataPrivate_tfAsTextFormatPrivate_tfHdrAsTextFormatPrivate_tfPgHdrAsTextFormatPrivate_marginAsSingle = 72 PublicFunctionCreatePDF(ByVal stream AsStream) AsInteger'' Set up some text formats:_tf = NewTextFormat() With { .Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "NotoSans-Regular.ttf")), .FontSize = 9, .ForeColor = Color.Black }_tfHdr = NewTextFormat(_tf) With { .Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "NotoSans-Bold.ttf")), .FontSize = 11, .ForeColor = Color.DarkBlue }_tfPgHdr = NewTextFormat(_tf) With { .FontSize = 11, .ForeColor = Color.Gray } '' The resulting PDF:Dim doc = NewGcPdfDocument()Using s = File.OpenRead(Path.Combine("Resources", "PDFs", "C1Olap-QuickStart.pdf"))Dim source = NewGcPdfDocument() source.Load(s)PrintAllTables(doc, source)EndUsing' Save the PDF: doc.Save(stream)'' Done:Return doc.Pages.CountEndFunction PrivateSubPrintAllTables(doc AsGcPdfDocument, source AsGcPdfDocument)'' Get the LogicalStructure and top parent element:Dim ls AsLogicalStructure = source.GetLogicalStructure()If ls IsNothingOrElse ls.ElementsIsNothingOrElse ls.Elements.Count = 0Then' No structure tags found:Util.AddNote("No structure tags were found in the source document.", doc.Pages.Add())ReturnEndIf' The root element:Dim root AsElement = ls.Elements(0) '' Find and print all tables:Dim tables = NewList(Of (TextLayout, Page))() root.Children.ToList().FindAll(Function(e_) e_.StructElement.Type = "Table").ForEach(Sub(t_) tables.Add(PrintTable(t_)))' Group tables by the page they were found on:Dim tablesByPage = tables.GroupBy(Function(t_) t_.Item2.Index)' For each page, print all tables found on that page,' followed by the original page for reference:ForEach tbp In tablesByPage' The page that will contain the extracted table data:Dim pgTables = doc.NewPage()' The page that will contain the source page for reference:Dim pgSrc = doc.NewPage()' Print the original page: tbp.First().Item2.Draw(pgSrc.Graphics, pgSrc.Bounds)' Add a page header: pgSrc.Graphics.DrawString($"Page {tbp.First().Item2.Index + 1} of the source PDF",_tfPgHdr, NewRectangleF(0, 0, pgSrc.Size.Width, _margin), TextAlignment.Center, ParagraphAlignment.Center, False)Dim maxHeight AsSingle = pgTables.Size.Height - _margin * 2Dim y AsSingle = _margin' Print all table data. For simplicity sake we assume that all table data will fit on a single page:ForEach t In tbp t.Item1.MaxHeight = maxHeight t.Item1.MaxWidth = pgTables.Size.Width - _margin * 2 pgTables.Graphics.DrawTextLayout(t.Item1, NewPointF(_margin, y)) maxHeight -= t.Item1.ContentHeight + _margin y += t.Item1.ContentHeight + _marginNextNextEndSub PrivateFunctionPrintTable(e AsElement) As (TextLayout, Page)If e.Type <> "Table"ThenThrowNew Exception($"Unexpected: element type must be 'Table' but it is '{e.Type}'.")EndIf Dim table = NewList(OfList(OfIList(OfITextParagraph)))()Dim maxCols = 0' Select all child elements with type TR - table rows:Dim selectRows As Action(OfIReadOnlyList(OfElement)) = Nothing selectRows = Sub(elements)ForEach ec AsElementIn elementsIf ec.HasChildrenThenIf ec.StructElement.Type = "TR"ThenDim cells = ec.Children.ToList().FindAll(Function(e_) e_.StructElement.Type = "TD").ToArray() maxCols = Math.Max(maxCols, cells.Length)Dim tableCells = NewList(OfIList(OfITextParagraph))()ForEach cell In cells tableCells.Add(cell.GetParagraphs())Next table.Add(tableCells)Else selectRows(ec.Children)EndIfEndIfNextEndSub selectRows(e.Children) '' Show table:Dim sourcePage = FindPage(e.StructElement)If sourcePage IsNothingThenThrowNew Exception("Unexpected: could not find the default page for the table.")EndIf Dim tl = NewTextLayout(72) ' Add table data to the text layout: tl.Append($"{vbLf}Table on page {sourcePage.Index + 1} of the source document has {maxCols} column(s) and {table.Count} row(s)." & vbLf & "Data by row:", _tfHdr) tl.AppendParagraphBreak()Dim irow = 0ForEach row In tableDim icol = 0ForEach cell In rowForEach para In cell tl.Append(para.GetText())NextIf row.IndexOf(cell) <= row.CountThen tl.Append(vbTab)Else tl.AppendLine()EndIf icol += 1Next irow += 1 tl.AppendLine()NextReturn (tl, sourcePage)EndFunction PrivateFunctionFindPage(se AsStructElement) AsPageIf se.DefaultPageIsNotNothingThenReturn se.DefaultPageEndIfIf se.HasChildrenThenForEach child In se.ChildrenDim p = FindPage(child)If p IsNotNothingThenReturn pEndIfNextEndIfReturnNothingEndFunctionEndClass