【问题标题】:Creating HTML from a DataTable using C#使用 C# 从 DataTable 创建 HTML
【发布时间】:2026-01-21 19:45:01
【问题描述】:

我需要能够像这样将 HTML 数据传递到 Outlook:

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

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

somestring.PadLeft(100);

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

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

  1. 如何将数据表转换为 html 表?
  2. 我的问题有更好的解决方案吗?

【问题讨论】:

  • 遍历 DataTable 的 Rows 和 Columns 集合,并从各个单元格值构建一个 html 字符串。
  • 它们占用不同数量的空间,因为您使用的字体不是等宽字体。也许等宽字体是一种解决方案。
  • @DJQuimby 非常感谢!!什么是等宽字体的示例?
  • @I__ 以下是一些列表:lowing.org/fonts
  • @DJQuimby 请看这个答案*.com/a/3288549/117700

标签: c# .net datatable outlook


【解决方案1】:

在这里写代码可能会很长,我同意@mservidio。请点击此链接查看您必须执行的操作示例:this link

【讨论】:

  • 附注:检查您的数据,如果它们不是数字,它们可能包含 HTML 的无效字符,因此原始 ToString() 不起作用(例如“
【解决方案2】:

遍历您的 DataTable,并构建 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 不是很好。我将如何在其中包装标签?
  • 我更新了代码 sn-p 以显示如何将其包装在标签中。有关使用 html 表的信息,请参阅此网址:w3schools.com/html/html_tables.asp
  • 如何使用此代码在表格周围添加边框?
【解决方案3】:

如何将数据表转换为 html 表?

唯一的方法是编写遍历每一行的代码并按照您需要的方式构建 HTML 字符串。

我的问题有更好的解决方案吗?

您可以使用等宽字体(例如Courier),只需输出正确数量的空格,您就可以正确对齐所有内容,但您仍然需要以 HTML 格式发送电子邮件,并设置正确的字体文件。

【讨论】:

    【解决方案4】:

    有多种方法可以输出 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 提供的答案
    【解决方案5】:

    我只想分享我所做的。我希望这会有所帮助。

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

    【讨论】:

      【解决方案6】:
      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();
              }
      

      【讨论】:

        【解决方案7】:
        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>";
        
            }
        

        【讨论】:

          【解决方案8】:
           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。
          【解决方案9】:

          这是我的版本,增加了基于通用规则(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();
              }
          

          【讨论】: