DynamicTable.vb
- ''
- '' This code is part of Document Solutions for PDF demos.
- '' Copyright (c) MESCIUS inc. All rights reserved.
- ''
- Imports System.IO
- Imports System.Drawing
- Imports System.Text
- Imports GrapeCity.Documents.Pdf
- Imports GrapeCity.Documents.Text
- Imports GrapeCity.Documents.Html
-
- '' This sample shows how to insert an HTML table with a varying number of rows
- '' that might not fit on a single page, into a PDF document starting at an arbitrary
- '' position on the page (all data rows must have the same height though).
- '' We first create a table with a single data row, measure its height,
- '' then create a similar table but with two data rows and measure it too.
- '' This allows us to find out the header and data rows' heights, and render
- '' the table to a PDF starting at the desired position on the page, and split
- '' it into additional pages as needed.
- ''
- '' Please see notes in comments at the top of HelloWorldHtml
- '' sample code for details on adding DsHtml to your projects.
- Public Class DynamicTable
- Function CreatePDF(ByVal stream As Stream) As Integer
- '' This tag is used to insert the prepared table HTML code
- '' into the HTML page template that defines the CSS styles etc.
- '' (Using this tag allows you to use string.Format when building
- '' the table HTML code, as otherwise curly braces in style
- '' definitions would interfere with format specifiers.)
- Const TTAG = "___TABLE___"
-
- '' The HTML page template:
- Const tableTpl =
- "<!DOCTYPE html>" +
- "<html>" +
- "<head>" +
- "<style>" +
- "#employees {" +
- " font-family: 'Trebuchet MS', Arial, Helvetica, sans-serif;" +
- " border-collapse: collapse;" +
- " width: 100%;" +
- "}" +
- "" +
- "#employees td, #employees th {" +
- " border: 1px solid #ddd;" +
- " padding: 8px;" +
- "}" +
- "" +
- "#employees tr:nth-child(even){background-color: #f2f2f2;}" +
- "" +
- "#employees tr:hover {background-color: #ddd;}" +
- "" +
- "#employees th {" +
- " padding-top: 12px;" +
- " padding-bottom: 12px;" +
- " text-align: left;" +
- " background-color: #3377ff;" +
- " color: white;" +
- "}" +
- "</style>" +
- "</head>" +
- "<body>" +
- "" +
- TTAG +
- "" +
- "</body>" +
- "</html>"
-
- '' The table HTML code format:
- Const tableFmt =
- "<table id='employees'>" +
- " <tr>" +
- " <th>Index</th>" +
- " <th>Lorem</th>" +
- " <th>Ipsum</th>" +
- " </tr>" +
- "{0}" +
- "</table>"
-
- '' The table row HTML code format:
- Const dataRowFmt =
- " <tr>" +
- " <td>{0}</td>" +
- " <td>{1}</td>" +
- " <td>{2}</td>" +
- " </tr>"
-
- '' Create a new PDF document:
- Dim doc = New GcPdfDocument()
- '' Add a page:
- Dim page = doc.NewPage()
- '' Add a page, get its graphics:
- Dim g = page.Graphics
-
- '' Set up HTML to PDF formatting options.
- '' The most important are the size limits, in this case
- '' we do not limit the height as we will adjust it programmatically.
- '' Note that in HtmlToPdfFormat, sizes are specified in inches:
- Dim hf = New HtmlToPdfFormat(False) With {.MaxPageWidth = page.Size.Width / 72}
-
- '' HTML code for a single data row (with sample data):
- Dim dataRow = String.Format(dataRowFmt, "a", "b", "c")
- '' HTML page with a table that has a single data row:
- Dim thtml = tableTpl.Replace(TTAG, String.Format(tableFmt, dataRow))
-
- '' Create an instance of GcHtmlBrowser that is used to render HTML:
- Using browser = Util.NewHtmlBrowser()
-
- '' Measure the HTML for the current GcPdfGraphics:
- Dim s1 = g.MeasureHtml(browser, thtml, hf)
- '' Same HTML page but with two data rows:
- thtml = tableTpl.Replace(TTAG, String.Format(tableFmt, dataRow + dataRow))
- '' Measure the new HTML:
- Dim s2 = g.MeasureHtml(browser, thtml, hf)
- '' Calculate data row and header row heights:
- Dim rowHeight = s2.Height - s1.Height
- Dim headerHeight = s1.Height - rowHeight
-
- '' Add a note at the top of the first page:
- Dim nrc = Util.AddNote(
- "Here we render an HTML table with an unknown number of rows " +
- "that starts at a specified position on the first page, " +
- "and may span multiple pages.",
- page)
-
- '' Set up for building the table with random data:
- Dim lorems = Util.LoremWords()
- Dim rnd = Util.NewRandom()
- Dim sb = New StringBuilder()
-
- '' Page layout parameters:
- Dim marginx = nrc.Left
- Dim marginy = nrc.Top
- Dim x = marginx
- Dim y = nrc.Bottom + 36
- Dim tbottom = nrc.Bottom + 36 + headerHeight
- '' A random number of data rows to render:
- Dim nrows = rnd.Next(100, 200)
- '' Generate and render the table, adding continuation pages as needed:
- For i = 0 To nrows - 1
- sb.AppendFormat(dataRowFmt, i, lorems(rnd.Next(lorems.Count)), lorems(rnd.Next(lorems.Count)))
- tbottom += rowHeight
- Dim lastPage = i = (nrows - 1)
- If tbottom >= page.Size.Height - 72 Or lastPage Then
- Dim html = tableTpl.Replace(TTAG, String.Format(tableFmt, sb.ToString()))
- Dim size As SizeF
- Dim ok = g.DrawHtml(browser, html, x, y, New HtmlToPdfFormat(False) With {.MaxPageWidth = (page.Size.Width - marginx * 2) / 72}, size)
- If Not lastPage Then
- page = doc.NewPage()
- g = page.Graphics
- y = 72
- tbottom = y + headerHeight
- sb.Clear()
- End If
- End If
- Next
-
- '' Done:
- doc.Save(stream)
- Return doc.Pages.Count
- End Using
- End Function
- End Class
-