MergeRows.vb
  1. ''
  2. '' This code is part of Document Solutions for PDF demos.
  3. '' Copyright (c) MESCIUS inc. All rights reserved.
  4. ''
  5. Imports System.IO
  6. Imports System.Drawing
  7. Imports System.Text
  8. Imports System.Data
  9. Imports System.Linq
  10. Imports System.Collections.Generic
  11. Imports GrapeCity.Documents.Pdf
  12. Imports GrapeCity.Documents.Text
  13. Imports GrapeCity.Documents.Html
  14.  
  15. '' This sample shows how to build and render a table-based report
  16. '' grouped by the first column, with that column's cells with same
  17. '' values merged.
  18. '' This sample uses a JavaScript code in the HTML to actually
  19. '' merge the cells, demonstrating the use of JavaScript when
  20. '' rendering HTML to PDF.
  21. '' Note that the sample limits the number of rows so that
  22. '' the whole table fits on a single page.
  23. ''
  24. '' Please see notes in comments at the top of HelloWorldHtml
  25. '' sample code for details on adding DsHtml to your projects.
  26. Public Class MergeRows
  27. Sub CreatePDF(ByVal stream As Stream)
  28. Const TTAG = "___TABLE___"
  29.  
  30. '' HTML page template:
  31. Const tableTpl =
  32. "<!DOCTYPE html>" +
  33. "<html>" +
  34. "<head>" +
  35. "<style>" +
  36. "" +
  37. "html * {" +
  38. " font-family: 'Trebuchet MS', Arial, Helvetica, sans-serif !important;" +
  39. "}" +
  40. "" +
  41. "h1 {" +
  42. " color: #1a5276;" +
  43. " background-color: #d2b4de;" +
  44. " text-align: center;" +
  45. " padding: 6px;" +
  46. "}" +
  47. "" +
  48. "thead {display: table-header-group;}" +
  49. "" +
  50. "#products {" +
  51. " font-family: 'Trebuchet MS', Arial, Helvetica, sans-serif;" +
  52. " border-collapse: collapse;" +
  53. " width: 100%;" +
  54. "}" +
  55. "" +
  56. "#products td, #products th {" +
  57. " border: 1px solid #ddd;" +
  58. " padding: 8px;" +
  59. "}" +
  60. "" +
  61. "#products tr:hover {background-color: #ddd;}" +
  62. "" +
  63. "#products th {" +
  64. " padding-top: 12px;" +
  65. " padding-bottom: 12px;" +
  66. " text-align: left;" +
  67. " background-color: #a569bd;" +
  68. " color: white;" +
  69. "}" +
  70. "</style>" +
  71. "" +
  72. "</head>" +
  73. "<body onload='mergeRows()'>" +
  74. "" +
  75. "<script>" +
  76. "function mergeRows() {" +
  77. " const table = document.querySelector('table');" +
  78. " let headerCell = null;" +
  79. " for (let row of table.rows)" +
  80. " {" +
  81. " const firstCell = row.cells[0];" +
  82. " if (headerCell === null || firstCell.innerText !== headerCell.innerText)" +
  83. " {" +
  84. " headerCell = firstCell;" +
  85. " }" +
  86. " else" +
  87. " {" +
  88. " headerCell.rowSpan++;" +
  89. " firstCell.remove();" +
  90. " }" +
  91. " }" +
  92. "}" +
  93. "</script>" +
  94. "" +
  95. TTAG +
  96. "" +
  97. "</body>" +
  98. "</html>"
  99.  
  100. Const tableHead = "<h1>Products by Suppliers</h1>"
  101.  
  102. Const tableFmt =
  103. "<table id='products'>" +
  104. " <thead>" +
  105. " <th>Supplier</th>" +
  106. " <th>Description</th>" +
  107. " <th>Quantity Per Unit</th>" +
  108. " <th>Unit Price</th>" +
  109. " </thead>" +
  110. "{0}" +
  111. "</table>"
  112.  
  113. Const dataRowFmt =
  114. " <tr>" +
  115. " <td>{0}</td>" +
  116. " <td>{1}</td>" +
  117. " <td>{2}</td>" +
  118. " <td align='right'>{3:C}</td>" +
  119. " </tr>"
  120.  
  121. Using ds = New DataSet()
  122. ds.ReadXml(Path.Combine("Resources", "data", "DsNWind.xml"))
  123.  
  124. Dim dtProds = ds.Tables("Products")
  125. Dim dtSupps = ds.Tables("Suppliers")
  126.  
  127. Dim products =
  128. (From prod In dtProds.Select()
  129. Join supp In dtSupps.Select()
  130. On prod("SupplierID") Equals supp("SupplierID")
  131. Order By supp("CompanyName")
  132. Select New With {
  133. .ProductName = prod("ProductName"),
  134. .Supplier = supp("CompanyName"),
  135. .QuantityPerUnit = prod("QuantityPerUnit"),
  136. .UnitPrice = prod("UnitPrice")
  137. }).Take(16)
  138.  
  139. Dim sb = New StringBuilder()
  140. sb.AppendLine(tableHead)
  141. For Each prod In products
  142. sb.AppendFormat(dataRowFmt, prod.Supplier, prod.ProductName, prod.QuantityPerUnit, prod.UnitPrice)
  143. Next
  144.  
  145. Dim html = tableTpl.Replace(TTAG, String.Format(tableFmt, sb.ToString()))
  146. Dim tmp = Path.GetTempFileName()
  147.  
  148. '' Create an instance of GcHtmlBrowser that is used to render HTML:
  149. Using browser = Util.NewHtmlBrowser()
  150. '' PdfOptions specifies options for HTML to PDF conversion:
  151. Dim pdfOptions = New PdfOptions() With {
  152. .Margins = New PdfMargins(0.2F, 1, 0.2F, 1),
  153. .DisplayHeaderFooter = True,
  154. .HeaderTemplate = "<div style='color:#1a5276; font-size:12px; width:1000px; margin-left:0.2in; margin-right:0.2in'>" +
  155. "<span style='float:left;'>Product Price List</span>" +
  156. "<span style='float:right'>Page <span class='pageNumber'></span> of <span class='totalPages'></span></span>" +
  157. "</div>",
  158. .FooterTemplate = "<div style='color: #1a5276; font-size:12em; width:1000px; margin-left:0.2in; margin-right:0.2in;'>" +
  159. "<span>(c) MESCIUS inc. All Rights Reserved.</span>" +
  160. "<span style='float:right'>Generated on <span class='date'></span></span></div>"
  161. }
  162. '' Render the source Web page to the temporary file:
  163. Using htmlPage = browser.NewPage(html)
  164. htmlPage.SaveAsPdf(tmp, pdfOptions)
  165. End Using
  166. End Using
  167. '' Copy the created PDF from the temp file to target stream:
  168. Using ts = File.OpenRead(tmp)
  169. ts.CopyTo(stream)
  170. End Using
  171. '' Clean up:
  172. File.Delete(tmp)
  173. End Using
  174. '' Done.
  175. End Sub
  176. End Class
  177.