【问题标题】:Export 5 million records to excel in asp.net using c#?使用c#将500万条记录导出到asp.net中的excel?
【发布时间】:2022-01-15 00:15:25
【问题描述】:

我想将数据库表导出到 Excel。 DB 表有大约 5 804 806 条记录,我想导出到 excel 中。

我尝试了不同的方法,但得到了

内存不足,无法继续执行程序

当我导出较少的数据时,下面的函数工作正常,但尝试提取包含 500 万条记录的报告时会引发内存不足错误。

我怎样才能实现它?

我用过但不工作的代码:

public static void GetExcelFromDataTable(DataTable dt, string fileName)
    {
        
       string attachment = "attachment; filename=" + fileName;
       HttpContext.Current.Response.ClearContent();
       HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
       HttpContext.Current.Response.AddHeader("content-disposition", string.Format("attachment;filename={0}.xls", fileName));
      //HttpContext.Current.Response.ContentType = "application/vnd.ms-excel"; //Excel 2003
       HttpContext.Current.Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; //Excel 2007
       string tab = "";
       foreach (DataColumn dc in dt.Columns)
       {
           HttpContext.Current.Response.Write(tab + dc.ColumnName);
           tab = "\t";
       }
       HttpContext.Current.Response.Write("\n");

       int i;
       foreach (DataRow dr in dt.Rows)
       {
           tab = "";
           for (i = 0; i < dt.Columns.Count; i++)
           {
               if (dr[i].ToString().Trim() == "\"")
               {
                   dr[i] = " \" ";
               }
               // HttpContext.Current.Response.Write(tab + dr[i].ToString());
               if (dr[i].ToString().StartsWith("0"))
               {
                   HttpContext.Current.Response.Write(tab + @"=""" + dr[i].ToString().Trim() + @"""");
               }
               else
               {
                   HttpContext.Current.Response.Write(tab + dr[i].ToString().Trim());
               }
               tab = "\t";
           }
           HttpContext.Current.Response.Write("\n");
       }
       HttpContext.Current.Response.End();
  

 
    }

ADO 代码:

if (ReportName == "SalesStatusVsMRPStatus")
            {
                query = "select Material,Material_Description,Eng_Resp,PLDv,SalesOrg,DC,Valid_from,SS,ItemCG,DelPlant,DelPlantMS,DelPlantValid_from,Grp From " + ReportName;
                //query = "SELECT TOP 10 * FROM " + ReportName;
            }
            else
            {
                query = "select * From " + ReportName;
            }
       

            SqlCommand cmd = new SqlCommand(query, cn);
            SqlDataAdapter adap = new SqlDataAdapter(cmd);
            DataTable dtUserData = new DataTable();
            cmd.CommandTimeout = 999999;
            cmd.CommandType = CommandType.Text;
            try
            {
                cn.Open();
                adap.Fill(dtUserData);
                foreach (DataColumn dc in dtUserData.Columns)
                {
                    if (dc.ColumnName == "Grp")
                    {
                        dc.ColumnName = "AuthGrp";
                    }
                }

            }
            catch (Exception ex)
            {
 
            }
            finally
            {
                cmd.Connection.Close();
                cn.Close();
                GridViewExportUtil.GetExcelFromDataTable(dtUserData, fileName);
            }

    }

我怎样才能实现它?

【问题讨论】:

  • 这能回答你的问题吗? T-SQL: Export to new Excel file
  • 根据 Excel 工作簿规范和可用的限制here,行数有一个硬性限制,为 1,048,576。
  • 在你的服务器上写一个 CSV 文件,压缩它,下载它。然后,您将在客户端上移动问题以读取该大文件。但是如果你需要备份,你可以写代码来做相反的事情(上传、解压缩、恢复)
  • 如果您真的想在您的服务器上执行此操作,您需要将您的处理分成多个批次(使用paginated queries)并一次处理合理数量的对象。当然,如果您的服务器根本没有保持 Excel 文件打开所需的 RAM 量,它仍然会崩溃,如果是这样,那么我建议您为单个 Excel 文件设置一个合理的最大值并进行批处理创建excel文件并创建多个Excel文件
  • 你为什么要这样做?单个 Excel 工作表中的行数不能超过 1M。这是一个硬限制。如果您使用 PowerPivot,您可以在其中放入内存允许 BUT 的数据,这些数据仅适用于 Excel 应用程序。您可以使用 Excel 互操作通过 PowerPivot 加载数据,但绝对不能在 Web 服务器上。具有 5M 行的 Excel 文件,即使拆分为多个工作表,也不是很有用。 Excel 是供人类使用的,而不是用于传输大量数据的

标签: c# sql asp.net


【解决方案1】:

我看到这里有 2 个问题:

  • 程序端内存分配
    DataAdapter 使用 DataSet,它会在关闭与 DB 的连接之前下载完整的表。因此,完整的表格首先需要在您的记忆中。如果读取后不需要编辑 DB 上的数据,可以使用 DataReader 代替。它是只读只进,并且每次只请求一条记录。因此不会消耗太多内存。虽然我使用的是 Oracle DB 版本,但您必须检查您的 DB 是否支持 C# 中的 DataReader。

  • Excel 限制
    甚至 .xlsx 也仅支持每张工作表 1,048,576 行。在制作 excel 文件时,您必须考虑更换工作表。

DataSet - 下载全表,支持DB编辑,检索到查询结果后可以离线工作。

DataReader - 只读,工作时需要一直连接DB。根据我自己使用 C# 和 Oracle DB 的经验,检索速度也快得多。

这篇文章有更多细节: Difference between Datareader, DataAdapter, Dataset, DataView

【讨论】:

    猜你喜欢
    • 2011-02-19
    • 1970-01-01
    • 2020-09-23
    • 2012-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多