我目前正在重构一个控制台应用程序,其主要职责是根据存储在数据库中的值生成报告。
我现在创建报告的方式如下:
const string format = "<tr><td>{0, 10}</td><td>
{1}</td><td>{2, 8}</td><td>{3}</td><td>{4, -30}</td>
<td>{5}</td><td>{6}</td></tr>";
if(items.Count > 0)
{
builder.AppendLine(
String.Format(format, "Date", "Id", "WorkItemId",
"Account Number", "Name", "Address", "Description"));
}
foreach(Item item in items)
{
builder.AppendLine(String.Format(format, item.StartDate, item.Id,
item.WorkItemId, item.AccountNumber,
String.Format("{0} {1}",
item.FirstName, item.LastName),
item.Address, item.Description));
}
string report = String.Format("<html><table border=\"1\">{0}
</table></html>",
builder.ToString());
(上面只是一个示例......对格式化感到抱歉......我试着将其格式化,因此不需要水平滚动....)
我真的不喜欢这样做我已经这样做了。它现在可以正常工作......但我认为它不可维护......特别是如果报告在需要创建的html方面变得更复杂的话。更糟糕的是,我的团队中的其他开发人员肯定会复制并粘贴我的代码,用于生成HTML报告的应用程序,并且可能会造成可怕的混乱。 (我已经看到了这样的恐怖产生!想象一下,报告函数有数百行硬编码的sql来检索报告的细节......它足以让一个成年男子哭泣!)
然而,虽然我根本不喜欢这个......我只是想不出一个不同的方式去做。
肯定有办法做到这一点......我很确定。不久前,我在aspx页面中生成表时做了同样的事情,直到有人向我展示我可以将对象绑定到控件并让.NET处理渲染。它将类似于上面代码的可怕代码变成了两三条优雅的优点。
有没有人知道在不对html进行硬编码的情况下为此报告创建html的类似方法?
答案 0 :(得分:10)
让您的应用生成包含原始数据的XML文件。然后将外部XSLT应用于包含HTML的外部XSLT。
答案 1 :(得分:4)
您可以使用NVelocity之类的模板引擎来分隔报告视图和代码。 那里可能还有其他不错的模板引擎......
答案 2 :(得分:3)
meziod - 另一种细读方法是HtmlTextWriter对象的扩展方法。在这个网站上,我发现了这一点。
我确信你可以从中获得巨大的潜力...
问候 - 可乐
答案 3 :(得分:2)
好吧,您可以使用其中一个报表框架(Crystal,MS RDL等)和 export 作为html - 但是,我怀疑对于简单数据,您当前的方法开销较小。我可能会使用XmlWriter
或LINQ-to-XML(而不是string.Format
,它不会处理转义)...
new XElement("tr",
new XElement("td", item.StartDate),
new XElement("td", item.Id),
new XElement("td", item.WorkItemId),
等。转义对于文本值(名称,描述等)尤其重要。
答案 4 :(得分:1)
您可以考虑使用简单的模板引擎,例如http://www.stefansarstedt.com/templatemaschine.html,并将模板与内容分开。
这非常实用,允许模板修改而无需重新编译,您的模板中仍然可以使用C#。
答案 5 :(得分:0)
Microsoft SQL Reporting Services可以很好地完成此任务,并且可以执行多种格式。
我的公司使用它来创建PDF报告,因为我们有HIPAA要求,我们会自动通过第三方PDF控件输入密码...
答案 6 :(得分:0)
正如coolashaka已经提到的,使用HtmlTextWriter是一个不错的选择,当然如果你添加了一些有用的扩展方法,例如:
简单示例:
public static void WriteNav(this
HtmlTextWriter writer, List<String> navItems)
{
writer.RenderBeginTag("nav");
writer.RenderBeginTag(HtmlTextWriterTag.Ul);
foreach (var item in navItems)
{
writer.RenderBeginTag(HtmlTextWriterTag.Ul);
writer.AddAttribute(HtmlTextWriterAttribute.Href, "~/" + item + ".html");
writer.RenderBeginTag(HtmlTextWriterTag.A);
writer.Write(item);
writer.RenderEndTag();
writer.RenderEndTag();
}
writer.RenderEndTag();
writer.RenderEndTag();
}
我知道这是一个老问题,但谷歌将在未来几年继续指导这里的人。