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