【发布时间】:2015-01-22 18:16:12
【问题描述】:
我的应用程序中有 10 个报告,我让用户导出到 Excel。我从来没有写过 CSV 文件。在我现有的应用程序中,我将存储过程的结果转换为 HTML 表并将其写入 Excel。我的一些存储过程的结果有动态列,所以我使用 dapper。我的新要求是也提供 CSV 导出。
所以我应该先将html数据表转换为excel并将其转换为CSV还是将HTML数据表写入CSV。我不想手动解析,因为有 10 种不同的报告具有不同的列,并且一些报告具有动态列,所以我无法手动解析。
存储的过程返回 Dapper、动态列
EFDbContext db = new EFDbContext();
var recordDate = StartDate.Date;
var cnn = new SqlConnection(db.Database.Connection.ConnectionString);
cnn.Open();
var p = new DynamicParameters();
p.Add("@StartDate", StartDate);
p.Add("@UserRoleID", UserRoleID);
p.Add("@SelectedSystemIDs", SelectedSystemIDs);
p.Add("@SelectedPartIDs", SelectedPartIDs);
p.Add("@SelectedSubSystems", SelectedSubsystems);
p.Add("@SelectedServiceTypes", SelectedServiceTypes);
var obs = cnn.Query(sql: "spExportInstrumentConfigAll", param: p, commandType: CommandType.StoredProcedure);
var dt = ToDataTable(obs);
return ExportDatatableToHtml(dt);
public static DataTable ToDataTable(IEnumerable<dynamic> items)
{
if (items == null) return null;
var data = items.ToArray();
if (data.Length == 0) return null;
var dt = new DataTable();
foreach (var pair in ((IDictionary<string, object>)data[0]))
{
dt.Columns.Add(pair.Key, (pair.Value ?? string.Empty).GetType());
}
foreach (var d in data)
{
dt.Rows.Add(((IDictionary<string, object>)d).Values.ToArray());
}
return dt;
}
public static string ExportDatatableToHtml(DataTable dt)
{
StringBuilder strHTMLBuilder = new StringBuilder();
strHTMLBuilder.Append("<html >");
strHTMLBuilder.Append("<head>");
strHTMLBuilder.Append("</head>");
strHTMLBuilder.Append("<body>");
strHTMLBuilder.Append("<table border='1px' cellpadding='1' cellspacing='1 style='font-family:Garamond; font-size:medium'>");
strHTMLBuilder.Append("<tr >");
foreach (DataColumn myColumn in dt.Columns)
{
strHTMLBuilder.Append("<td >");
strHTMLBuilder.Append(myColumn.ColumnName);
strHTMLBuilder.Append("</td>");
}
strHTMLBuilder.Append("</tr>");
foreach (DataRow myRow in dt.Rows)
{
strHTMLBuilder.Append("<tr >");
foreach (DataColumn myColumn in dt.Columns)
{
strHTMLBuilder.Append("<td >");
strHTMLBuilder.Append(myRow[myColumn.ColumnName].ToString());
strHTMLBuilder.Append("</td>");
}
strHTMLBuilder.Append("</tr>");
}
//Close tags.
strHTMLBuilder.Append("</table>");
strHTMLBuilder.Append("</body>");
strHTMLBuilder.Append("</html>");
string Htmltext = strHTMLBuilder.ToString();
return Htmltext;
}
映射到实体的非动态列
return db.Database.SqlQuery<ServiceEntryPartExportDataRow>("[dbo].[spExportServiceParts] @parm1, @parm2, @parm3, @parm4,@parm5,@parm6",
new SqlParameter("parm1", StartDate),
new SqlParameter("parm2", EndDate),
new SqlParameter("parm3", Reconciled),
new SqlParameter("parm4", ServiceTypes),
new SqlParameter("parm5", SelectedSystemIDs),
new SqlParameter("parm6", UserRoleID)
).ToList().ToHTMLTable();
public static string ToHTMLTable<T>(this IList<T> data)
{
PropertyDescriptorCollection props =
TypeDescriptor.GetProperties(typeof(T));
StringBuilder builder = new StringBuilder();
builder.Append("<table border=\"1\">");
builder.Append("<tr>");
for (int i = 0; i < props.Count; i++)
{
builder.Append("<td>");
PropertyDescriptor prop = props[i];
builder.Append(prop.Name);
builder.Append("</td>");
}
builder.Append("</tr>");
object[] values = new object[props.Count];
foreach (T item in data)
{
builder.Append("<tr>");
for (int i = 0; i < values.Length; i++)
{
builder.Append("<td>");
builder.Append(props[i].GetValue(item));
builder.Append("</td>");
}
builder.Append("</tr>");
}
builder.Append("</table>");
return "<html><body>" + builder.ToString() + "</body></html";
}
当前代码发送到 Excel
return new PostActionResult(htmlTable, "ServiceEntryHistory", submit);
public PostActionResult(string htmlTable, string typeName, string submit) { this.htmlTable = htmlTable; this.typeName = typeName; this.submit = submit; }
public PostActionResult(DataTable dataTable, string typeName, string submit) { this.dataTable = dataTable; this.typeName = typeName; this.submit = submit; }
public override void ExecuteResult(ControllerContext context)
{
if (submit == "Excel")
{
ExcelHelpers.ExportToExcel(context.HttpContext, typeName, htmlTable);
}
if (submit == "CSV")
{
ExcelHelpers.ExportToExcelCSV(context.HttpContext, typeName, htmlTable);
}
}
public static void ExportToExcel(HttpContextBase httpBase, string fileNamePrefix, string table)
{
string TimeStamp = DateTime.Now.ToLocalTime().ToString();
string fileName = string.Format("attachment;filename={0}_{1}.xls", fileNamePrefix, TimeStamp);
httpBase.Response.ClearHeaders();
httpBase.Response.ClearContent();
httpBase.Response.Clear();
httpBase.Response.AddHeader("content-disposition", fileName);
httpBase.Response.ContentType = "application/vnd.ms-excel";
httpBase.Response.Write(table);
httpBase.Response.End();
}
【问题讨论】:
-
实际的结构化数据在哪里?将记录集合导出到 CSV 相当简单。它基本上是一个循环和一个字符串生成器。 “动态列”不是问题。如果您有列名,则将它们打印为文件的第一行。如果不这样做,则只需打印其他内容(例如
Column{0}带有递增的整数)。 -
您在 ASP.NET 环境中使用 Office Interop,即bad idea。您应该停止这样做,并使用能够在不依赖 Interop 的情况下生成所需的本机 Excel 文件的库。如果你搜索“c# generate excel file”,你应该会得到很多有用的库。
-
@David 我发布了我的整个代码。对于具有动态列输出的报告,我使用 dapper,对于具有非动态列的报告,我映射了实体
-
@user721:构建 CSV 的代码与构建 HTML 表的代码几乎相同。您只能使用逗号、引号(特别是对于其中带有逗号的值)和回车符来代替 HTML 标记。除此之外,结构完全相同。事实上,CSV 与 HTML 是模板方法模式的经典示例。
标签: c# asp.net sql-server-2008 asp.net-mvc-3