MergeRows.cs
C# VB
//// This code is part of Document Solutions for Imaging demos.// Copyright (c) MESCIUS inc. All rights reserved.//using System;using System.IO;using System.Drawing;using System.Text;using System.Data;using System.Linq;using GrapeCity.Documents.Html;
namespace DsImagingWeb.Demos{ // This sample shows how to build and render a table-based report // grouped by the first column, with that column's cells with same // values merged. // This sample uses a JavaScript code in the HTML to actually // merge the cells, demonstrating the use of JavaScript when // rendering HTML to images. // Note that the sample limits the number of rows so that // the whole table fits in the image. // // Please see notes in comments at the top of HelloWorldHtml // sample code for details on adding DsHtml to your projects. public class MergeRows { public Stream GenerateImageStream(string targetMime, Size pixelSize, float dpi, bool opaque, string[] sampleParams = null) { const string TTAG = "___TABLE___";
// HTML page template: 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 onload='mergeRows()'>" +
// solution from https://stackoverflow.com/questions/56587070/merge-neighbouring-html-table-cells-with-same-value-using-js "<script>" + "function mergeRows() {" + " const table = document.querySelector('table');" + " let headerCell = null;" + " for (let row of table.rows)" + " {" + " const firstCell = row.cells[0];" + " if (headerCell === null || firstCell.innerText !== headerCell.innerText)" + " {" + " headerCell = firstCell;" + " }" + " else" + " {" + " headerCell.rowSpan++;" + " firstCell.remove();" + " }" + " }" + "}" + "</script>" +
TTAG +
"</body>" + "</html>";
const string tableHead = "<h1>Products by Suppliers</h1>";
const string tableFmt = "<table id='products'>" + " <thead>" + " <th>Supplier</th>" + " <th>Description</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 align='right'>{3:C}</td>" + " </tr>";
DataSet ds = new DataSet(); ds.ReadXml(Path.Combine("Resources", "data", "GcNWind.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 supp["CompanyName"] select new { ProductName = prod["ProductName"], Supplier = supp["CompanyName"], QuantityPerUnit = prod["QuantityPerUnit"], UnitPrice = prod["UnitPrice"] }).Take(16);
var sb = new StringBuilder(); sb.AppendLine(tableHead); foreach (var prod in products) sb.AppendFormat(dataRowFmt, prod.Supplier, prod.ProductName, prod.QuantityPerUnit, prod.UnitPrice);
var html = tableTpl.Replace(TTAG, string.Format(tableFmt, sb.ToString()));
var tfile = Path.GetTempFileName(); var ms = new MemoryStream(); // We use GcHtmlBrowser to render the whole generated HTML to an image. // Note that GcHtmlBrowser natively supports only JPEG, PNG and WEBP formats. // In this sample we limit the output to those formats. // For a more flexible approach that allows rendering HTML into any // image format supported by DsImaging, please see HtmlRenderPage0. using var browser = Common.Util.NewHtmlBrowser(); using var htmlPage = browser.NewPage(html, new PageOptions() { WindowSize = pixelSize }); tfile = Path.GetTempFileName(); switch (targetMime) { case Common.Util.MimeTypes.JPEG: htmlPage.SaveAsJpeg(tfile); break; case Common.Util.MimeTypes.PNG: htmlPage.SaveAsPng(tfile); break; case Common.Util.MimeTypes.WEBP: htmlPage.SaveAsWebp(tfile); break; default: throw new Exception("Unsupported image format."); } // Copy the created image from the temp file to target stream: using (var ts = File.OpenRead(tfile)) ts.CopyTo(ms); // Clean up: File.Delete(tfile); // Done. return ms; } }}