ASP.NET C#中如何在excel中下载gridview,即如何在datatable中使用group by

Posted

技术标签:

【中文标题】ASP.NET C#中如何在excel中下载gridview,即如何在datatable中使用group by【英文标题】:how to download gridview in excel in ASP.NET C #, ie How to use group by in datatable 【发布时间】:2021-10-14 01:43:36 【问题描述】:

如果我有一个具有以下布局的数据表:

Column1 Column2
First Number1
First Number2
Second Number1
Second Number2
Second Number3

我需要在 Excel 中的 gridview 中下载数据表才能像这里的表格:

Column
First
Number1
Number2
Second
Number1
Number2
Number3

我见过很多使用 LINQ,但我是新手,所以我不太擅长 LINQ。

你能帮忙吗?

代码:

private DataTable QR (int ID) 

    string conn = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString.ToString();

    SqlConnection sqlConnection = new SqlConnection(conn);
    string queryQ = @"some query here to take data from database";
       
    sqlConnection.Open();

    SqlCommand cmd = new SqlCommand(queryQ, sqlConnection);
    cmd.Parameters.AddWithValue("@ID", ID);

    SqlDataReader dr = cmd.ExecuteReader();
    dataTableQ  = new DataTable();
    dataTableQ.Load(dr);

    // after that I'm little confused 
    DataTable dtq = new DataTable();
    var l = new List<string>();
    var gg = dtq.Rows.Cast<DataRow>().GroupBy(r => (string)r["QT"]);

    foreach (var g in gg)
    
        l.Add(g.Key);

        foreach (var r in g)
            l.Add((string)r["SubQT"]);
    
        
    HttpContext.Current.Session["_dataTableForExportInExcel1"] = dtq;
    return dtq;

谢谢

【问题讨论】:

【参考方案1】:

呃,准备好用这种“按位置关联”的想法弄乱你的数据的事故

我也不会为此使用 LINQ

var l = new List<string>();
string prev = null;
foreach(DataRow r in dt.Rows)
  var s = (string)r["Column1"];
  var t = (string)r["Column2"];

  if(s != prev)
    l.Add(s);
    prev = s;
   
  l.Add(t);
 

渴望使用 LINQ 的东西?

var l = new List<string>();
var gg = dt.Rows.Cast<DataRow>().GroupBy(r => (string)r["Column1"]);
foreach(var g in gg)
  l.Add(g.Key);
  foreach(var r in g)
    l.Add((string)r["Column2"]);
 

因此您希望将输出作为数据表 - 添加到数据表而不是列表:

var l = new DataTable();
l.Columns.Add("X");
string prev = null;
foreach(DataRow r in dt.Rows)
  var s = (string)r["Column1"];
  var t = (string)r["Column2"];

  if(s != prev)
    l.Rows.Add(s);
    prev = s;
   
  l.Rows.Add(t);
 

【讨论】:

不,LINQ 不是这个问题的绑定解决方案。我认为 LINQ 是最好的,但欢迎所有解决方案,只是为了解决这个问题。 它可以很好地实践,但重要的是要意识到 LINQ 通常只是编写一些循环的简写方式,有时简洁并不能转化为清晰或性能;D 你能帮帮我吗,我有点迷失在代码中。这是我填写网格的代码。 cmets 中的代码几乎无法遵循;您应该编辑问题...您似乎已将数据加载到一个数据表中,然后将另一个空表分组,然后丢弃生成的列表并将一个空表添加到会话中 我是一个更新问题,我是新来的,所以在我管理的时候。【参考方案2】:

好吧,您可以将网格处理成 csv,或者实际上,我建议您在驱动、填充网格视图的表上执行此操作。

假设我们有这个:

        <asp:GridView ID="GridView1" runat="server" CssClass="table table-hover">
        </asp:GridView>

        <br />
        <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="As Csv" Width="126px" />
        <br />
        <br />

好的,我们填充这个网格视图的代码是这样的:

  protected void Page_Load(object sender, EventArgs e)
    
        if (!IsPostBack)
        
            GridView1.DataSource = LoadGrid();
            GridView1.DataBind();
        
    

    DataTable LoadGrid()
    
        DataTable dt = new DataTable();
        using (SqlCommand cmdSQL =
            new SqlCommand("SELECT City, HotelName from tblHotels ORDER BY City, HotelName",
            new SqlConnection(Properties.Settings.Default.TEST3)))
        
            cmdSQL.Connection.Open();
            dt.Load(cmdSQL.ExecuteReader());
        
        return dt;
    

好的,此时输出是这样的:

所以,我们希望按城市分组为一列。 (真的和你的例子一样的问题)。

所以按钮代码是这样的:

   protected void Button1_Click(object sender, EventArgs e)
    
        DataTable dt = new DataTable();
        dt = LoadGrid();

        DataTable OutTable = new DataTable();
        OutTable.Columns.Add("C1", typeof(string));

        string strGroup = "";
        foreach (DataRow dRow in dt.Rows)
        
            if (dRow[0].ToString() != strGroup)
            
                strGroup = dRow[0].ToString();
                OutTable.Rows.Add(strGroup);
            
            OutTable.Rows.Add(dRow[1].ToString());
        

        Response.ClearContent();
        Response.AddHeader("content-disposition", "attachment;filename=mydata.csv");
        Response.Write(toCsvT(OutTable));
        Response.End();
    

csv 例程的表格是这样的:

   public string toCsvT(DataTable dt)
    
        string strCSV = "";
        string q = "\"";
        // csv heading
        foreach (DataColumn hCol in dt.Columns)
        
            if (strCSV != "")
                strCSV += ",";
            strCSV += q + hCol.ColumnName + q;
        
        strCSV += System.Environment.NewLine;

        // csv data
        foreach (DataRow dRow in dt.Rows)
        
            string strOneRow = "";
            for (var i = 0; i <= dRow.Table.Columns.Count - 1; i++)
            
                if (strOneRow != "")
                    strOneRow += ",";
                strOneRow += q + dRow[i] + q;
            
            strCSV += strOneRow + System.Environment.NewLine;
        
        return strCSV;
    

因此,我们可能已经处理了 DataGrid 上的每一行,但最好花时间创建一个表到 csv 例程 - 我们可以在许多其他地方使用该例程。

所以,我强烈建议将表格(数据源)重新处理为新的所需格式。

但是,您可以使用非常接近我用于数据表的相同代码,并使用数据网格行作为数据源(您可以使用 DataGridItem 中的 .cells[0] 和 .cells1(每行). 但我认为上面的更好。

这个,当我们点击按钮时,它会下载,然后点击打开,我们会得到这个:

【讨论】:

以上是关于ASP.NET C#中如何在excel中下载gridview,即如何在datatable中使用group by的主要内容,如果未能解决你的问题,请参考以下文章

Asp.net Core-在使用 javascript 或 C# 上传之前选择和验证 excel 文件?

asp.net(C#)如何将查询到的数据导出Excel表格?

[ASP.NET][C#]下载文件时中文文件名出现乱码

asp.net(C#)之NPOI&quot;操作Excel

c# asp.net 页面上的多个表导出到一个excel文件中

如何使用 c# 将 JQgrid 数据导出到 Excel?