ProductList.cs
// 完毕:
using System;
using System.IO;
using System.Drawing;
using System.Text;
using System.Data;
using System.Linq;
using System.Collections.Generic;
using GrapeCity.Documents.Pdf;
using GrapeCity.Documents.Text;
using GrapeCity.Documents.Html;

namespace DsPdfWeb.Demos
{
    // 此示例展示了如何呈现报告(产品列表)
    // 来自标准 NWind 示例数据库)使用 HTML 字符串
    // 作为模板。通过循环数据记录来创建报告
    // 并从表格行模板构建生成的 HTML,其中填充
    // 实际数据。然后将生成的 HTML 字符串传递给 GcHtmlRenderer
    // 创建 PDF。
    // 
    // 请参阅HelloWorldHtml顶部评论中的注释
    // 有关将 GcDocs.Html 添加到项目的详细信息的示例代码。
    public class ProductList
    {
        public void CreatePDF(Stream stream)
        {
            const string TTAG = "___TABLE___";

            // HTML 页面模板:
            const string tableTpl =
                "<!DOCTYPE html>" +
                "<html>" +
                "<head>" +
                "<style>" +

                "html * {" +
                "  font-family: 'Trebuchet MS', Arial, Helvetica, sans-serif !important;" +
                "}" +

                "h1 {" +
                "  color: #1a5276;" +
                "  background-color: #d2b4de;" +
                "  text-align: center;" +
                "  padding: 6px;" +
                "}" +

                "thead {display: table-header-group;}" +

                "#products {" +
                "  font-family: 'Trebuchet MS', Arial, Helvetica, sans-serif;" +
                "  border-collapse: collapse;" +
                "  width: 100%;" +
                "}" +

                "#products td, #products th {" +
                "  border: 1px solid #ddd;" +
                "  padding: 8px;" +
                "}" +

                "#products tr:nth-child(even){background-color: #f2f2f2;}" +

                "#products tr:hover {background-color: #ddd;}" +

                "#products th {" +
                "  padding-top: 12px;" +
                "  padding-bottom: 12px;" +
                "  text-align: left;" +
                "  background-color: #a569bd;" +
                "  color: white;" +
                "}" +
                "</style>" +
                "</head>" +
                "<body>" +

                TTAG +

                "</body>" +
                "</html>";

            const string tableHead = "<h1>Product Price List</h1>";

            const string tableFmt =
                "<table id='products'>" +
                "  <thead>" +
                "    <th>Product ID</th>" +
                "    <th>Description</th>" +
                "    <th>Supplier</th>" +
                "    <th>Quantity Per Unit</th>" +
                "    <th>Unit Price</th>" +
                "  </thead>" +
                "{0}" +
                "</table>";

            const string dataRowFmt =
                "  <tr>" +
                "    <td>{0}</td>" +
                "    <td>{1}</td>" +
                "    <td>{2}</td>" +
                "    <td>{3}</td>" +
                "    <td align='right'>{4:C}</td>" +
                "  </tr>";

            using var ds = new DataSet();
            ds.ReadXml(Path.Combine("Resources", "data", "DsNWind.xml"));

            DataTable dtProds = ds.Tables["Products"];
            DataTable dtSupps = ds.Tables["Suppliers"];

            var products =
                from prod in dtProds.Select()
                join supp in dtSupps.Select()
                on prod["SupplierID"] equals supp["SupplierID"]
                orderby prod["ProductName"]
                select new
                {
                    ProductID = prod["ProductID"],
                    ProductName = prod["ProductName"],
                    Supplier = supp["CompanyName"],
                    QuantityPerUnit = prod["QuantityPerUnit"],
                    UnitPrice = prod["UnitPrice"]
                };

            var sb = new StringBuilder();
            sb.AppendLine(tableHead);
            foreach (var prod in products)
                sb.AppendFormat(dataRowFmt, prod.ProductID, prod.ProductName, prod.Supplier, prod.QuantityPerUnit, prod.UnitPrice);

            var html = tableTpl.Replace(TTAG, string.Format(tableFmt, sb.ToString()));

            using var browser = Common.Util.NewHtmlBrowser();
            using var htmlPage = browser.NewPage(html);

            // PdfOptions 允许您提供 HTML 到 PDF 转换的选项:
            var pdfOptions = new PdfOptions()
            {
                Margins = new PdfMargins(0.2f, 1, 0.2f, 1),
                DisplayHeaderFooter = true,
                HeaderTemplate = "<div style='color:#1a5276; font-size:12px; width:1000px; margin-left:0.2in; margin-right:0.2in'>" +
                    "<span style='float:left;'>Product Price List</span>" +
                    "<span style='float:right'>Page <span class='pageNumber'></span> of <span class='totalPages'></span></span>" +
                    "</div>",
                FooterTemplate = "<div style='color: #1a5276; font-size:12em; width:1000px; margin-left:0.2in; margin-right:0.2in;'>" +
                    "<span>(c) MESCIUS inc. All Rights Reserved.</span>" +
                    "<span style='float:right'>Generated on <span class='date'></span></span></div>"
            };
            // 将源网页渲染到临时文件:
            var tmp = Path.GetTempFileName();
            htmlPage.SaveAsPdf(tmp, pdfOptions);

            // 将创建的 PDF 从临时文件复制到目标流:
            using (var ts = File.OpenRead(tmp))
                ts.CopyTo(stream);
            // 清理:
            File.Delete(tmp);

            // 完毕:
        }
    }
}