我应该将 excel 转换为 csv 还是将 htmltable 写入 csv

Should I Convert excel to csv or write htmltable to csv

我的应用程序中有 10 个报告,我允许用户将其导出到 excel。我从来没有写过 CSV 文件。在我现有的应用程序中,我将存储过程的结果转换为 HTML table 并将其写入 Excel。我从存储过程中得到的一些结果有动态列,所以我使用 dapper。我的新要求是也提供 CSV 导出。

所以我应该先将html数据table转换成excel再转换成CSV还是把HTML数据table写成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();
        }

您已经有了根据数据构建 HTML table 的代码。构建 CSV 几乎完全相同。为了简洁起见,让我们简化一下HTML table 伪代码:

builder.Append("<table>");

// header
builder.Append("<tr>");
foreach (var column in columns)
    builder.Append("<th>" + column.name + "</th>");
builder.Append("</tr>");

// rows
foreach (var row in rows)
{
    builder.Append("<tr>");
    foreach (var column in row.columns)
        builder.Append("<td>" + column.value + "</td>");
    builder.Append("</tr>");
}

builder.Append("</table>");

构建 CSV 是完全相同的结构:

// header
foreach (var column in columns)
    builder.Append("\"" + column.name + "\",");
// there's now an extra comma at the end.  remove it, or use a
// different method to have built the row, such as string.Join.

// rows
foreach (var row in rows)
{
    foreach (var column in row.columns)
        builder.Append("\"" + column.value + "\",");
    // there's now an extra comma at the end.  remove it, or use a
    // different method to have built the row, such as string.Join.
    builder.Append(Environment.NewLine);
}

请记住,这是徒手编写的伪代码,您可以进行一些清理工作。您还可以检查列类型以确定是否需要这些转义引号,因为数字类型不需要它们。但关键是结构是一样的。 CSV 是文本,与 HTML 是文本的方式相同。只是价值观的着装不同。

旁注:这实际上是Template Method Pattern的经典示例。