DynamicTable.vb
'' 完毕:
Imports System.IO
Imports System.Drawing
Imports System.Text
Imports GrapeCity.Documents.Pdf
Imports GrapeCity.Documents.Text
Imports GrapeCity.Documents.Html

'' 此示例演示如何插入具有不同行数的 HTML 表格
'' 可能无法容纳在单个页面上,而是以任意位置开始的 PDF 文档
'' 页面上的位置(但所有数据行必须具有相同的高度)。
'' 我们首先创建一个包含单个数据行的表,测量其高度,
'' 然后创建一个类似的表,但有两个数据行并对其进行测量。
'' 这使我们能够找出标题和数据行的高度,并渲染
'' 从页面上所需的位置开始将表格转换为 PDF,然后拆分
'' 根据需要将其放入其他页面。
'' 
'' 请参阅HelloWorldHtml顶部评论中的注释
'' 有关将 GcDocs.Html 添加到项目的详细信息的示例代码。
Public Class DynamicTable
    Function CreatePDF(ByVal stream As Stream) As Integer
        '' 该标签用于插入准备好的表格HTML代码
        '' 到定义 CSS 样式等的 HTML 页面模板中。
        '' (使用此标签允许您在构建时使用 string.Format
        '' 表 HTML 代码,否则样式中的大括号
        '' 定义会干扰格式说明符。)
        Const TTAG = "___TABLE___"

        '' HTML 页面模板:
        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>"

        '' 表格HTML代码格式:
        Const tableFmt =
                "<table id='employees'>" +
                "  <tr>" +
                "    <th>Index</th>" +
                "    <th>Lorem</th>" +
                "    <th>Ipsum</th>" +
                "  </tr>" +
                "{0}" +
                "</table>"

        '' 表格行HTML代码格式:
        Const dataRowFmt =
                "  <tr>" +
                "    <td>{0}</td>" +
                "    <td>{1}</td>" +
                "    <td>{2}</td>" +
                "  </tr>"

        '' 创建一个新的 PDF 文档:
        Dim doc = New GcPdfDocument()
        '' 添加页面:
        Dim page = doc.NewPage()
        '' 添加一个页面,获取其图形:
        Dim g = page.Graphics

        '' 设置 HTML 到 PDF 格式选项。
        '' 最重要的是大小限制,在这种情况下
        '' 我们不限制高度,因为我们将以编程方式调整它。
        '' 请注意,在 HtmlToPdfFormat 中,尺寸以英寸为单位指定:
        Dim hf = New HtmlToPdfFormat(False) With {.MaxPageWidth = page.Size.Width / 72}

        '' 单个数据行的 HTML 代码(带有示例数据):
        Dim dataRow = String.Format(dataRowFmt, "a", "b", "c")
        '' 包含一个包含单个数据行的表的 HTML 页面:
        Dim thtml = tableTpl.Replace(TTAG, String.Format(tableFmt, dataRow))

        '' 创建一个用于呈现 HTML 的 GcHtmlBrowser 实例:
        Using browser = Util.NewHtmlBrowser()

            '' 测量当前 GcPdfGraphics 的 HTML:
            Dim s1 = g.MeasureHtml(browser, thtml, hf)
            '' 相同的 HTML 页面,但有两个数据行:
            thtml = tableTpl.Replace(TTAG, String.Format(tableFmt, dataRow + dataRow))
            '' 测量新的 HTML:
            Dim s2 = g.MeasureHtml(browser, thtml, hf)
            '' 计算数据行和标题行高度:
            Dim rowHeight = s2.Height - s1.Height
            Dim headerHeight = s1.Height - rowHeight

            '' 在第一页顶部添加注释:
            Dim nrc = Util.AddNote(
                "这里我们渲染一个行数未知的 HTML 表格" +
                "",
                page)

            '' 设置使用随机数据构建表:
            Dim lorems = Util.LoremWords()
            Dim rnd = Util.NewRandom()
            Dim sb = New StringBuilder()

            '' 页面布局参数:
            Dim marginx = nrc.Left
            Dim marginy = nrc.Top
            Dim x = marginx
            Dim y = nrc.Bottom + 36
            Dim tbottom = nrc.Bottom + 36 + headerHeight
            '' 要呈现的随机数量的数据行:
            Dim nrows = rnd.Next(100, 200)
            '' 生成并呈现表格,根据需要添加延续页面:
            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

            '' 完毕:
            doc.Save(stream)
            Return doc.Pages.Count
        End Using
    End Function
End Class