使用C#从DataTable创建HTML

8
我需要能够像这样将HTML数据传递到Outlook中:
MailMessage message = new MailMessage();
message.Body = myBody;

起初,我认为可以将纯文本传递给它,并像下面这样使用PadLeft

somestring.PadLeft(100);

但是它没有正确对齐一切,因为即使|||||MMMMM都只有5个字符的长度,在屏幕上它们在物理上占用更多的空间。

我的解决方案是将我的datatable中的数据转换成HTML表格,然后将其传递到Outlook。

  1. 如何将datatable转换为HTML表格?
  2. 是否有更好的解决方案来解决我的问题?

2
遍历 DataTable 的行和列集合,并从单元格值构建一个 html 字符串。 - mservidio
1
它们占用不同的空间,因为您使用的字体不是等宽字体。也许等宽字体是一个解决方案。 - DJ Quimby
@DJQuimby 非常感谢!! 有一个等宽字体的示例是什么? - Alex Gordon
@DJQuimby 请查看这个回答 http://stackoverflow.com/a/3288549/117700 - Alex Gordon
@I__ 感谢您指出这一点,我没有考虑到! - DJ Quimby
显示剩余2条评论
9个回答

17

遍历您的数据表,构建HTML字符串。例如:

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>");

非常感谢!很抱歉我的HTML不是很好。我该如何将标签包起来? - Alex Gordon
我已经更新了代码片段,以展示如何将其包装在标签中。有关使用HTML表格的信息,请参阅以下网址:http://www.w3schools.com/html/html_tables.asp - mservidio
我该如何使用这段代码在表格周围添加边框? - user3486773

6
我想分享一下我所做的事情。希望这能有所帮助。
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());
}

3

代码在此处写起来可能会很长,我同意@mservidio的说法。请点击这个链接查看需要完成的示例。


顺便提一下:检查你的数据,如果它们不是数字,则可能包含HTML的无效字符,所以原始的ToString()方法不起作用(例如"<")。 - Adriano Repetti

3
如何将数据表格转换为HTML表格?
唯一的方法是编写代码,遍历每行并构建您需要的HTML字符串。
是否有更好的解决方案?
您可以使用等宽字体(例如Courier),这样只需输出正确数量的空格即可正确对齐所有内容,但仍需要在文档中设置正确的字体以HTML格式发送电子邮件。

3
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>";

    }

1

有许多方法可以输出 HTML。

如果这是一个相对简单的格式(没有太多格式、样式等),我肯定会选择 @mservidio 的建议。

如果输出更复杂,并且您具有 ASP.NET 的经验,您可以选择使用 UserControl,它允许更灵活和管理输出。 然后,您可以像这样将控件的输出呈现为 HTML:

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

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

如果很简单的话,我会选择@mservidio提供的答案。 - Shai Cohen

0
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();
        }

0
这是我的版本,增加了根据通用规则(rowHighlightRule参数)“高亮”某些行的可能性。
  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();
    }

-1
 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;
    }

他没有说JPG,而是HTML。 - dipi evil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接