Alex Gordon
Alex Gordon

Reputation: 60741

Creating HTML from a DataTable using C#

I need to be able to pass HTML data into Outlook like this:

MailMessage message = new MailMessage();
message.Body = myBody;

Initially, I thought I could pass plain text to it and use PadLeft like this:

somestring.PadLeft(100);

but it did not align everything properly because even though ||||| and MMMMM are both only 5 characters in length, they physically on the screen take up more space.

My solution is to convert data that is in my datatable into an HTML table and then pass it into Outlook.

  1. how do I convert a datatable into an html table?
  2. is there a better solution to my issue?

Upvotes: 8

Views: 43694

Answers (9)

Adriano Repetti
Adriano Repetti

Reputation: 67090

Code could be pretty long to write here, I agree with @mservidio. Follow this link to see an example of what you have to do: this link

Upvotes: 3

Michele Ferracin
Michele Ferracin

Reputation: 407

This is my version of it, with added the possibility to "highlight" some rows based on a generic rule (rowHighlightRule parameter).

  public static string ToHTML(this DataTable dt, Func<DataRow, bool> rowHiglithRule)
    {

        if (dt == null) throw new ArgumentNullException("dt");

        string tab = "\t";

        StringBuilder sb = new StringBuilder();
        sb.AppendLine(tab + tab + "<table>");

        // headers.
        sb.Append(tab + tab + tab + "<thead><tr>");

        foreach (DataColumn dc in dt.Columns)
        {
            sb.AppendFormat("<td>{0}</td>", dc.ColumnName);
        }

        sb.AppendLine("</thead></tr>");

        // data rows
        foreach (DataRow dr in dt.Rows)
        {
            if (rowHiglithRule != null)
            {

                if (rowHiglithRule(dr))
                {
                    sb.Append(tab + tab + tab + "<tr class=\"highlightedRow\">");
                }
                else
                {
                    sb.Append(tab + tab + tab + "<tr>");
                }
            }
            else
            {
                //Non ho alcuna regola, quindi caso normale.
                sb.Append(tab + tab + tab + "<tr>");
            }

            foreach (DataColumn dc in dt.Columns)
            {
                string cellValue = dr[dc] != null ? dr[dc].ToString() : "";
                sb.AppendFormat("<td>{0}</td>", cellValue);
            }

            sb.AppendLine("</tr>");
        }

        sb.AppendLine(tab + tab + "</table>");


        return sb.ToString();
    }

Upvotes: 0

Dr.sai
Dr.sai

Reputation: 305

 public string MakeJPGFromDataTable(DataTable dt)
    {
        Font fnt = new System.Drawing.Font("verdana", 10,FontStyle.Bold);
        string strPath = Path.GetTempPath();
        string strJPG = "";
        strPath += "Publisher";
        Directory.CreateDirectory(strPath);
        Graphics grfx = CreateGraphics();
        float nWdBMP = 0;
        float nHtBMP = 0;

        var TalleststringLength = dt.AsEnumerable().Max(row => row.ItemArray.Max(x => grfx.MeasureString(x.ToString(), fnt).Height));
        var longeststringLength = dt.AsEnumerable().Max(row => row.ItemArray.Max(x => grfx.MeasureString(x.ToString(), fnt).Width));
        //string ss =  dt.Columns[1].ToString();
        //int[] nColHeaderLengths = (from z in new int[7] { 0, 1, 2, 3, 4, 5, 6 } select dt.Columns.Cast<DataColumn>().Max(dc => (int)grfx.MeasureString(dt.Columns[z].ToString(), fnt).Width)).ToArray();
        //int[] nColWidths = (from z in new int[7] { 0, 1, 2, 3, 4, 5, 6 } select dt.AsEnumerable().Max(row => (int)grfx.MeasureString(row.ItemArray[z].ToString(), fnt).Width)).ToArray();
        var xx = (from x in dt.Columns.Cast<DataColumn>() select x.Ordinal).ToArray();
        var nColWidths = (from z in (xx)
                           select dt.AsEnumerable().Max(row =>
                               (grfx.MeasureString(row.ItemArray[z].ToString(), fnt).Width >
                               grfx.MeasureString(dt.Columns[z].ToString(), fnt).Width)
                               ? grfx.MeasureString(row.ItemArray[z].ToString(), fnt).Width
                               : grfx.MeasureString(dt.Columns[z].ToString(), fnt).Width)
            ).ToArray();

        nWdBMP = nColWidths.Sum();
        nHtBMP = TalleststringLength * (dt.Rows.Count + 1);
        int xPos = 0;
        int yPos = 0;
        int nMargin = 10;

        Bitmap mapMem = new Bitmap((int)nWdBMP + (nMargin * (dt.Columns.Count + 1)), (int)nHtBMP);
        Graphics grfxMem = Graphics.FromImage(mapMem);
        grfxMem.SmoothingMode = SmoothingMode.HighQuality;
        grfxMem.InterpolationMode = InterpolationMode.HighQualityBicubic;
        grfxMem.PixelOffsetMode = PixelOffsetMode.HighQuality;
        grfxMem.CompositingQuality = CompositingQuality.GammaCorrected;

        grfxMem.FillRectangle(lgBackgroundBrush,0,0,mapMem.Width,mapMem.Height);

        for (int j = 0; j < dt.Columns.Count; j++)
        {
            grfxMem.DrawString(dt.Columns[j].ToString(), fnt, lgFontBrush, xPos, yPos);
            //xPos += (int)grfx.MeasureString(dt.Columns[j].ToString(), fnt).Width;
            xPos += (int)nColWidths[j] + nMargin;
        }
        xPos = 0;
        yPos += (int)TalleststringLength;
        grfxMem.DrawLine(pen, new Point(0, yPos), new Point((int)mapMem.Width, yPos));
        //foreach (DataRow dr in dt.Rows)
        //{
        //    for (int j = 0; j < dt.Columns.Count; j++)
        //    {
        //        grfxMem.DrawString(dr[j].ToString(), fnt, Brushes.Blue, xPos, yPos);
        //        xPos += (int)nColWidths[j] + nMargin;
        //    }
        //    xPos = 0;
        //    yPos += (int)TalleststringLength;
        //}
        int s = 0;
        Func<object, bool> too_much_where = delegate(object itemCurrent)
        {
            grfxMem.DrawString(itemCurrent.ToString(), fnt, lgFontBrush, xPos, yPos);
            xPos += (int)nColWidths[s++] + nMargin;
            if (s >= dt.Columns.Count)
            {
                //Know what this determines the end of every row
                s = 0;
                xPos = 0;
                yPos += (int)TalleststringLength;
                grfxMem.DrawLine(pen, new Point(0, yPos), new Point((int)mapMem.Width, yPos));
            }
            return false;
        };
        //var sizzeler = (from dr in dt.AsEnumerable()
        //                let drItems = (from itemCurrent in dr.ItemArray select itemCurrent)
        //                               from item in drItems
        //                                where too_much_where(item)
        //                    select new
        //                    {
        //                        z = true,
        //                    }
        //                ).ToArray();
        var sizzeler = (from dr in dt.AsEnumerable()
                        where (dr.ItemArray.Where(itemCurrent => too_much_where(itemCurrent)).Count() == 0)
                        select new
                        {
                            z = true,
                        }
                        ).ToArray();
        s = 0;
        for (int j = 0; j < nColWidths.Length; j ++)
        {
            grfxMem.DrawLine(pen, new Point(s, 0), new Point(s, (int)mapMem.Height));
            s += (int)(nColWidths[j] + nMargin );
        }
        s = mapMem.Width-1;
        grfxMem.DrawRectangle(pen, new Rectangle(0, 0, mapMem.Width - 1, mapMem.Height - 1));
        s = 0;
        grfx.DrawImage(mapMem, (float)10.0, (float)10.0);
        grfx.Dispose();
        return strJPG;
    }

Upvotes: -1

Dr.sai
Dr.sai

Reputation: 305

public string ConvertDataTableToHTMLTableInOneLine(DataTable dt)
    {
        //Convert DataTable To HTML Table in one line
        return "<table>\n<tr>" + string.Join("", dt.Columns.Cast<DataColumn>().Select(dc => "<td>" + dc.ColumnName + "</td>")) + "</tr>\n" +
        "<tr>" + string.Join("</tr>\n<tr>", dt.AsEnumerable().Select(row => "<td>" + string.Join("</td><td>", row.ItemArray) + "</td>").ToArray()) + "</tr>\n<\table>";

    }

Upvotes: 3

Suman Banerjee
Suman Banerjee

Reputation: 1961

public string toHTML_Table(DataTable dt)
        {
            if (dt.Rows.Count == 0)
                return "";

            StringBuilder builder = new StringBuilder();
            builder.Append("<html>");
            builder.Append("<head>");
            builder.Append("<title>");
            builder.Append("Page-");
            builder.Append(Guid.NewGuid().ToString());
            builder.Append("</title>");
            builder.Append("</head>");
            builder.Append("<body>");
            builder.Append("<table border='1px' cellpadding='5' cellspacing='0' ");
            builder.Append("style='border: solid 1px Silver; font-size: x-small;'>");
            builder.Append("<tr align='left' valign='top'>");
            foreach (DataColumn c in dt.Columns)
            {
                builder.Append("<td align='left' valign='top'><b>");
                builder.Append(c.ColumnName);
                builder.Append("</b></td>");
            }
            builder.Append("</tr>");
            foreach (DataRow r in dt.Rows)
            {
                builder.Append("<tr align='left' valign='top'>");
                foreach (DataColumn c in dt.Columns)
                {
                    builder.Append("<td align='left' valign='top'>");
                    builder.Append(r[c.ColumnName]);
                    builder.Append("</td>");
                }
                builder.Append("</tr>");
            }
            builder.Append("</table>");
            builder.Append("</body>");
            builder.Append("</html>");

            return builder.ToString();
        }

Upvotes: 0

Andamon A. Abilar
Andamon A. Abilar

Reputation: 171

I just want to share what I did. I hope this would help.

using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.IO;

public void Build(DataSet ds) 
{
    StringWriter sw = new StringWriter();
    HtmlTextWriter w = new HtmlTextWriter(sw);

    foreach (DataTable dt in ds.Tables) 
    {
        //Create a table
        Table tbl = new Table();

        //Create column header row
        TableHeaderRow thr = new TableHeaderRow();
        foreach (DataColumn col in dt.Columns) {
            TableHeaderCell th = new TableHeaderCell();
            th.Text = col.Caption;
            thr.Controls.Add(th);
        }
        tbl.Controls.Add(thr);

        //Create table rows
        foreach (DataRow row in dt.Rows)
        {
            TableRow tr = new TableRow();
            foreach (var value in row.ItemArray)
            {
                TableCell td= new TableCell();
                td.Text = value.ToString();
                tr.Controls.Add(td);
            }
            tbl.Controls.Add(tr);
        }

        tbl.RenderControl(w);

    }

    Response.Write(sw.ToString());
}

Upvotes: 6

mservidio
mservidio

Reputation: 13057

Loop over your DataTable, and build up the html string. IE:

DataTable dt = new DataTable();

dt.Columns.Add("col1");
dt.Columns.Add("col2");
dt.Columns.Add("col3");
dt.Rows.Add(new object[] { "a", "b", "c" });
dt.Rows.Add(new object[] { "d", "e", "f" });

string tab = "\t";

StringBuilder sb = new StringBuilder();

sb.AppendLine("<html>");
sb.AppendLine(tab + "<body>");
sb.AppendLine(tab + tab + "<table>");

// headers.
sb.Append(tab + tab + tab + "<tr>");

foreach (DataColumn dc in dt.Columns)
{        
    sb.AppendFormat("<td>{0}</td>", dc.ColumnName);        
}

sb.AppendLine("</tr>");

// data rows
foreach (DataRow dr in dt.Rows)
{
    sb.Append(tab + tab + tab + "<tr>");

    foreach (DataColumn dc in dt.Columns)
    {
        string cellValue = dr[dc] != null ? dr[dc].ToString() : "";
        sb.AppendFormat("<td>{0}</td>", cellValue);
    }

    sb.AppendLine("</tr>");
}

sb.AppendLine(tab + tab + "</table>");
sb.AppendLine(tab + "</body>");
sb.AppendLine("</html>");

Upvotes: 17

Shai Cohen
Shai Cohen

Reputation: 6249

There are a number of ways to output the HTML.

If this is a relatively easy format (not much formatting, styles etc.) I would definitely go with @mservidio's suggestion.

If the output is more complex and you have experience with ASP.NET you can go the route of a UserControl which allows more flexibility and management of the output. You can then render the output of the control to HTML like this:

StringBuilder sb = new StringBuilder();
StringWriter tw = new StringWriter(sb);
HtmlTextWriter hw = new HtmlTextWriter(tw);

ctrl.RenderControl(hw);
return sb.ToString();

Upvotes: 1

Icarus
Icarus

Reputation: 63966

how do i convert a datatable into an html table?

The only way is to write code that goes through every row and builds the HTML string the way you need it.

is there a better solution to my issue?

You could use a monospace font (such as Courier) wihch will allow you to align everything properly by simply outputting the right number of spaces but you'd still need to send the email in HTML format setting the proper font on the document.

Upvotes: 3

Related Questions