将 DataTable 导出到 Excel 文件

38

我有一个包含30多个列和6500多行的DataTable。我需要将整个DataTable值转储到Excel文件中。请问有谁可以帮忙提供C#代码?我需要每个列值都在一个单元格中。准确地说,我需要在Excel文件中得到与DataTable完全相同的外观副本。请求帮助。

谢谢, Vix


你可以尝试这里描述的技术:C-Sharp Corner - Randolpho
1
几乎所有在这里的答案都是编写(HtmlTextWriter)字符串或具有Interop代码。 不要使用它们,否则您将在稍后与DateTime和Decimal格式设置方面遇到问题。 另外,Excel会发出警告,因为您生成的不是“真正”的Excel文件,而是一个带有.xls扩展名的HTML页面。开始使用专用库创建Excel文件,例如[EPPlus](https://github.com/JanKallman/EPPlus)。 [示例在这里](https://stackoverflow.com/a/47293207/5836671)和[这里](https://dev59.com/vJrga4cB1Zd3GeqPr8im#39513057)。 - VDWWD
13个回答

80

使用这段代码...

    dt = city.GetAllCity();//your datatable
    string attachment = "attachment; filename=city.xls";
    Response.ClearContent();
    Response.AddHeader("content-disposition", attachment);
    Response.ContentType = "application/vnd.ms-excel";
    string tab = "";
    foreach (DataColumn dc in dt.Columns)
    {
        Response.Write(tab + dc.ColumnName);
        tab = "\t";
    }
    Response.Write("\n");
    int i;
    foreach (DataRow dr in dt.Rows)
    {
        tab = "";
        for (i = 0; i < dt.Columns.Count; i++)
        {
            Response.Write(tab + dr[i].ToString());
            tab = "\t";
        }
        Response.Write("\n");
    }
    Response.End();

4
在我浏览网络上所有复杂的文章来完成这个任务之后,很高兴找到了一个简短、简单且有效的解决方案。非常感谢! - brian newman
1
有没有什么建议可以强制Excel将所有字段视为字符串,而不考虑数据类型?例如,在“0000012”中不要删除前导零。我尝试在值前加上撇号,但是撇号出现在电子表格中。 - brian newman
2
为什么这对我实际上没有任何作用?即使我逐字复制它,它也不会下载文件... - Glendale
1
这段代码下载一个没有任何格式的CSV文件;如果您需要更多关于合并单元格、背景单元格颜色等方面的灵活性,您应该阅读本问题的其他答案。 - Rubens Farias
这不是一个纯粹的Excel文件,只是文本保存为Excel :( - Marcio
显示剩余2条评论

11
这段代码的实现速度可以更快:
// Example data
DataTable table = new DataTable();
table.Columns.AddRange(new[]{ new DataColumn("Key"), new DataColumn("Value") });
foreach (string name in Request.ServerVariables)
    table.Rows.Add(name, Request.ServerVariables[name]);

// This actually makes your HTML output to be downloaded as .xls file
Response.Clear();
Response.ClearContent();
Response.ContentType = "application/octet-stream";
Response.AddHeader("Content-Disposition", "attachment; filename=ExcelFile.xls");

// Create a dynamic control, populate and render it
GridView excel = new GridView();
excel.DataSource = table;
excel.DataBind();
excel.RenderControl(new HtmlTextWriter(Response.Output));

Response.Flush();
Response.End();

这个对我没用,它输出的是一个Excel文件,但其中包含与https协议相关的表格,如(SERVER_PORT_SECURE, SERVER_PROTOCOL, SERVER_SOFTWARE),我不太清楚这是什么...似乎更好的方法是我们不需要覆盖VerifyRenderingInServerForm...你能帮我吗? - sam
我错过了什么?我把那段代码放在方法中,并从按钮的onclick事件中调用它。 - sam
我需要返回任何东西吗? - chungtinhlakho
@chungtinhlakho,这个方法呈现一个HTML表格并将其写入响应流中;如果您遇到其他问题,请提出新的问题 ;) - Rubens Farias

5
这篇文章中提供的答案很简单,但是它是CSV文件而不是真正的Excel文件。因此,在打开文件时会收到警告。 我在网上找到的最佳解决方案是使用CloseXML,你也需要打开XML。 https://github.com/closedxml/closedxml
 dt = city.GetAllCity();//your datatable
 using (XLWorkbook wb = new XLWorkbook())
    {
        wb.Worksheets.Add(dt);

        Response.Clear();
        Response.Buffer = true;
        Response.Charset = "";
        Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
        Response.AddHeader("content-disposition", "attachment;filename=GridView.xlsx");
        using (MemoryStream MyMemoryStream = new MemoryStream())
        {
            wb.SaveAs(MyMemoryStream);
            MyMemoryStream.WriteTo(Response.OutputStream);
            Response.Flush();
            Response.End();
        }
    }

来源: http://www.aspsnippets.com/Articles/Solution-ASPNet-GridView-Export-to-Excel-The-file-you-are-trying-to-open-is-in-a-different-format-than-specified-by-the-file-extension.aspx

本文是关于ASP.NET GridView导出到Excel时遇到“您尝试打开的文件与文件扩展名指定的格式不同”的解决方案。

@jefissu 看起来 ClosedXML 在旧版本的 .Net Framework 中存在已知问题。请参考 https://github.com/ClosedXML/ClosedXML/issues/450。 - Amir

5
以下链接是用于在C#代码中将数据表导出到Excel的。 http://royalarun.blogspot.in/2012/01/export-datatable-to-excel-in-c-windows.html
  using System;      
   using System.Data;  
   using System.IO;  
   using System.Windows.Forms;  

    namespace ExportExcel  
    {      
        public partial class ExportDatatabletoExcel : Form  
        {  
            public ExportDatatabletoExcel()  
            {  
                InitializeComponent();  
            }  

            private void Form1_Load(object sender, EventArgs e)
            {

                DataTable dt = new DataTable();

                //Add Datacolumn
                DataColumn workCol = dt.Columns.Add("FirstName", typeof(String));

                dt.Columns.Add("LastName", typeof(String));
                dt.Columns.Add("Blog", typeof(String));
                dt.Columns.Add("City", typeof(String));
                dt.Columns.Add("Country", typeof(String));

                //Add in the datarow
                DataRow newRow = dt.NewRow();

                newRow["firstname"] = "Arun";
                newRow["lastname"] = "Prakash";
                newRow["Blog"] = "http://royalarun.blogspot.com/";
                newRow["city"] = "Coimbatore";
                newRow["country"] = "India";

                dt.Rows.Add(newRow);

                //open file
                StreamWriter wr = new StreamWriter(@"D:\\Book1.xls");

                try
                {

                    for (int i = 0; i < dt.Columns.Count; i++)
                    {
                        wr.Write(dt.Columns[i].ToString().ToUpper() + "\t");
                    }

                    wr.WriteLine();

                    //write rows to excel file
                    for (int i = 0; i < (dt.Rows.Count); i++)
                    {
                        for (int j = 0; j < dt.Columns.Count; j++)
                        {
                            if (dt.Rows[i][j] != null)
                            {
                                wr.Write(Convert.ToString(dt.Rows[i][j]) + "\t");
                            }
                            else
                            {
                                wr.Write("\t");
                            }
                        }
                        //go to next line
                        wr.WriteLine();
                    }
                    //close file
                    wr.Close();
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
        }
    }

实际上这不是一个Excel创建过程。它生成制表符分隔的纯文本,并将数据保存在扩展名为.xls的文件中。由于Microsoft Excel软件能够打开此类文件,人们认为它是一个Excel文档。在任何纯文本编辑器(如“记事本”或“EditPlus”)中打开同一文件,您就会知道。Microsoft Excel文档遵循OLE原则。我希望这可以帮助那些试图跟进此线程的人。 - Sudhakar Chavali

2

我在页面中使用了这个。

 public void DTToExcel(DataTable dt)
{
    // dosya isimleri ileride aynı anda birden fazla kullanıcı aynı dosya üzerinde işlem yapmak ister düşüncesiyle guid yapıldı. 
    string FileName = Guid.NewGuid().ToString();

    FileInfo f = new FileInfo(Server.MapPath("Downloads") + string.Format("\\{0}.xlsx", FileName));
    if (f.Exists)
        f.Delete(); // delete the file if it already exist.

    HttpResponse response = HttpContext.Current.Response;
    response.Clear();
    response.ClearHeaders();
    response.ClearContent();
    response.Charset = Encoding.UTF8.WebName;
    response.AddHeader("content-disposition", "attachment; filename=" + FileName + ".xls");
    response.AddHeader("Content-Type", "application/Excel");
    response.ContentType = "application/vnd.xlsx";
    //response.AddHeader("Content-Length", file.Length.ToString());


    // create a string writer
    using (StringWriter sw = new StringWriter())
    {
        using (HtmlTextWriter htw = new HtmlTextWriter(sw)) //datatable'a aldığımız sorguyu bir datagrid'e atayıp html'e çevir.
        {
            // instantiate a datagrid
            DataGrid dg = new DataGrid();
            dg.DataSource = dt;
            dg.DataBind();
            dg.RenderControl(htw);
            response.Write(sw.ToString());
            dg.Dispose();
            dt.Dispose();
            response.End();
        }
    }
}

谢谢 Volkan,这是最好的方法,因为我们不需要覆盖 VerifyRenderingInServerForm.... Volkan,我非常感谢你在每行上设置注释以解释发生了什么,这对于其他人也很有用.. 我推荐这种方式给亲爱的搜索者们 - sam
Volkan,亲爱的,请您看一下当我取消对这行代码的注释时,为什么会报错?我在尝试理解它的目的是什么?//response.AddHeader("Content-Length", file.Length.ToString()); - sam
我已经为我理解的行添加了一些注释,请提供更多信息...非常感谢。 - sam

1
            var lines = new List<string>();

            string[] columnNames = dt.Columns.Cast<DataColumn>().
                                              Select(column => column.ColumnName).
                                              ToArray();

            var header = string.Join(",", columnNames);
            lines.Add(header);
            var valueLines = dt.AsEnumerable()
                               .Select(row => string.Join(",", row.ItemArray));
            lines.AddRange(valueLines);
            File.WriteAllLines("excel.csv", lines);

这里的“dt”是指您作为参数传递的数据表。

0

Excel导出的可用代码

 try
        {
            DataTable dt = DS.Tables[0];
            string attachment = "attachment; filename=log.xls";
            Response.ClearContent();
            Response.AddHeader("content-disposition", attachment);
            Response.ContentType = "application/vnd.ms-excel";
            string tab = "";
            foreach (DataColumn dc in dt.Columns)
            {
                Response.Write(tab + dc.ColumnName);
                tab = "\t";
            }
            Response.Write("\n");
            int i;
            foreach (DataRow dr in dt.Rows)
            {
                tab = "";
                for (i = 0; i < dt.Columns.Count; i++)
                {
                    Response.Write(tab + dr[i].ToString());
                    tab = "\t";
                }
                Response.Write("\n");
            }
            Response.End();
        }
        catch (Exception Ex)
        { }

1
你为什么将已接受的答案重新发布为你自己的答案? - devlin carnate

0

大多数答案实际上是生成 CSV,但我在 Excel 中打开时并不总是有良好的体验。

另一种方法是使用 ACE OLEDB Provider(也可以参见Excel 的连接字符串)。当然,您必须安装和注册提供程序。如果您安装了 Excel,则已经拥有它,但这是部署时需要考虑的问题(例如,在 Web 服务器上)。

在下面的帮助程序类代码中,您需要调用类似于 ExportHelper.CreateXlsFromDataTable(dataset.Tables[0], @"C:\tmp\export.xls"); 的内容。

public class ExportHelper
{
    private const string ExcelOleDbConnectionStringTemplate = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 8.0;HDR=YES\";";

    /// <summary>
    /// Creates the Excel file from items in DataTable and writes them to specified output file.
    /// </summary>
    public static void CreateXlsFromDataTable(DataTable dataTable, string fullFilePath)
    {
        string createTableWithHeaderScript = GenerateCreateTableCommand(dataTable);

        using (var conn = new OleDbConnection(String.Format(ExcelOleDbConnectionStringTemplate, fullFilePath)))
        {
            if (conn.State != ConnectionState.Open)
            {
                conn.Open();
            }

            OleDbCommand cmd = new OleDbCommand(createTableWithHeaderScript, conn);
            cmd.ExecuteNonQuery();

            foreach (DataRow dataExportRow in dataTable.Rows)
            {
                AddNewRow(conn, dataExportRow);
            }
        }
    }

    private static void AddNewRow(OleDbConnection conn, DataRow dataRow)
    {
        string insertCmd = GenerateInsertRowCommand(dataRow);

        using (OleDbCommand cmd = new OleDbCommand(insertCmd, conn))
        {
            AddParametersWithValue(cmd, dataRow);
            cmd.ExecuteNonQuery();
        }
    }

    /// <summary>
    /// Generates the insert row command.
    /// </summary>
    private static string GenerateInsertRowCommand(DataRow dataRow)
    {
        var stringBuilder = new StringBuilder();
        var columns = dataRow.Table.Columns.Cast<DataColumn>().ToList();
        var columnNamesCommaSeparated = string.Join(",", columns.Select(x => x.Caption));
        var questionmarkCommaSeparated = string.Join(",", columns.Select(x => "?"));

        stringBuilder.AppendFormat("INSERT INTO [{0}] (", dataRow.Table.TableName);
        stringBuilder.Append(columnNamesCommaSeparated);
        stringBuilder.Append(") VALUES(");
        stringBuilder.Append(questionmarkCommaSeparated);
        stringBuilder.Append(")");
        return stringBuilder.ToString();
    }

    /// <summary>
    /// Adds the parameters with value.
    /// </summary>
    private static void AddParametersWithValue(OleDbCommand cmd, DataRow dataRow)
    {
        var paramNumber = 1;

        for (int i = 0; i <= dataRow.Table.Columns.Count - 1; i++)
        {
            if (!ReferenceEquals(dataRow.Table.Columns[i].DataType, typeof(int)) && !ReferenceEquals(dataRow.Table.Columns[i].DataType, typeof(decimal)))
            {
                cmd.Parameters.AddWithValue("@p" + paramNumber, dataRow[i].ToString().Replace("'", "''"));
            }
            else
            {
                object value = GetParameterValue(dataRow[i]);
                OleDbParameter parameter = cmd.Parameters.AddWithValue("@p" + paramNumber, value);
                if (value is decimal)
                {
                    parameter.OleDbType = OleDbType.Currency;
                }
            }

            paramNumber = paramNumber + 1;
        }
    }

    /// <summary>
    /// Gets the formatted value for the OleDbParameter.
    /// </summary>
    private static object GetParameterValue(object value)
    {
        if (value is string)
        {
            return value.ToString().Replace("'", "''");
        }
        return value;
    }

    private static string GenerateCreateTableCommand(DataTable tableDefination)
    {
        StringBuilder stringBuilder = new StringBuilder();
        bool firstcol = true;

        stringBuilder.AppendFormat("CREATE TABLE [{0}] (", tableDefination.TableName);

        foreach (DataColumn tableColumn in tableDefination.Columns)
        {
            if (!firstcol)
            {
                stringBuilder.Append(", ");
            }
            firstcol = false;

            string columnDataType = "CHAR(255)";

            switch (tableColumn.DataType.Name)
            {
                case "String":
                    columnDataType = "CHAR(255)";
                    break;
                case "Int32":
                    columnDataType = "INTEGER";
                    break;
                case "Decimal":
                    // Use currency instead of decimal because of bug described at 
                    // http://social.msdn.microsoft.com/Forums/vstudio/en-US/5d6248a5-ef00-4f46-be9d-853207656bcc/localization-trouble-with-oledbparameter-and-decimal?forum=csharpgeneral
                    columnDataType = "CURRENCY";
                    break;
            }

            stringBuilder.AppendFormat("{0} {1}", tableColumn.ColumnName, columnDataType);
        }
        stringBuilder.Append(")");

        return stringBuilder.ToString();
    }
}

0

尽管不是.NET实现,但您可能会发现插件TableTools对于您的受众非常有效。它依赖于Flash,这在大多数需要深入工作并想要记录表格信息的情况下不应该成为问题。

最新版本似乎支持将内容复制到剪贴板、CSV、".XLS"(实际上只是一个名为.xls的制表符分隔文件),PDF,或创建一个打印友好页面版本,其中显示所有行和其余页面内容隐藏。

我在DataTables网站上找到了该扩展程序,链接在此处:http://datatables.net/extras/tabletools/

下载可在插件(额外)页面上获得,链接在此处:http://datatables.net/extras/

据说它是DataTables的一部分进行下载(因此出现了短语“Extras included in the DataTables package”),但我没有在我使用的下载中找到它。看起来运行得非常好!


-1
请尝试这个方法,它可以更快地将数据表中的数据导出到Excel。
注意:我硬编码的“FW”范围是因为我有179列。
public void UpdateExcelApplication(SqlDataTable dataTable)
    {
        var objects = new string[dataTable.Rows.Count, dataTable.Columns.Count];

        var rowIndex = 0;

        foreach (DataRow row in dataTable.Rows)
        {
            var colIndex = 0;

            foreach (DataColumn column in dataTable.Columns)
            {
                objects[rowIndex, colIndex++] = Convert.ToString(row[column]);
            }

            rowIndex++;
        }

        var range = this.workSheet.Range[$"A3:FW{dataTable.Rows.Count + 2}"];
        range.Value = objects;

        this.workSheet.Columns.AutoFit();
        this.workSheet.Rows.AutoFit();
    }

“worksheet”是一种工作表类型。它在哪里声明、初始化等。 - Deepak

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接