如何将DataTable导出到Excel

use*_*221 98 .net c# datatable

如何DataTable在C#中导出到Excel?我正在使用Windows窗体.它DataTableDataGridView控件相关联.我必须将记录导出DataTable到Excel.

hmq*_*esy 120

我推荐ClosedXML -

您可以使用一些非常易读的代码将DataTable转换为Excel工作表:

XLWorkbook wb = new XLWorkbook();
DataTable dt = GetDataTableOrWhatever();
wb.Worksheets.Add(dt,"WorksheetName");
Run Code Online (Sandbox Code Playgroud)

开发人员响应迅速,乐于助人.该项目积极开发,文档非常精湛.

  • 添加~6 MB的引用库不会使应用程序变得很重? (7认同)
  • 好问题@MicheleVirgilio.我还没有做过任何量化影响的测试.但是对于它的价值,在我使用它的任何项目中都没有困扰我,实际上我不能说我曾经注意到它. (4认同)
  • 添加大型数据表(在我的例子中为 250k 行)导致 ClosedXML 内存不足,这是一个已知的开放问题 (3认同)

cuo*_*gle 67

尝试简单的代码,将DataTable转换为excel文件为csv:

var lines = new List<string>();

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

var header = string.Join(",", columnNames.Select(name => $"\"{name}\""));
lines.Add(header);

var valueLines = dataTable.AsEnumerable()
    .Select(row => string.Join(",", row.ItemArray.Select(val => $"\"{val}\"")));

lines.AddRange(valueLines);

File.WriteAllLines("excel.csv", lines);
Run Code Online (Sandbox Code Playgroud)

这会将一个新文件excel.csv写入"当前工作目录",通常是.exe所在的位置或启动它的位置.

请注意,输出会excel.csv在dataTable中已包含的数据之间放置逗号().由于它不会在数据中转义逗号,因此读取文件的程序会错误地解释数据中的逗号.

  • 多么好的答案,伙计。我没有余力对你的答案投出超过一票的赞成票,否则我可能会投出超过 100 票的赞成票。 (2认同)
  • @Cuong Le - 如果单元格有两个逗号,那么“string.Join(",")”就会出现问题 (2认同)
  • @suneelranga - 如果一个单元格(即在 row.ItemArray 中)包含一个 `,`(逗号),那么根据 CSV 标准,该单元格应该用引号 `","` 括起来,然后像往常一样出现在文件中。所以,是的 - 它会导致问题,因为此代码不会检测`,` 并应用引号。 (2认同)
  • `File.WriteAllLines(ExcelFilePath,lines,Encoding.UTF8);` 用于 unicode (2认同)

tun*_*lik 39

一个优雅的选择是为.net框架的DataTable类编写扩展方法(见下文).

这种扩展方法可以如下调用:

using System;
using System.Collections.Generic;
using System.Linq;
using Excel = Microsoft.Office.Interop.Excel;
using System.Data;
using System.Data.OleDb;

DataTable dt;
// fill table data in dt here 
...

// export DataTable to excel
// save excel file without ever making it visible if filepath is given
// don't save excel file, just make it visible if no filepath is given
dt.ExportToExcel(ExcelFilePath);
Run Code Online (Sandbox Code Playgroud)

DataTable类的扩展方法:

public static class My_DataTable_Extensions
{

    // Export DataTable into an excel file with field names in the header line
    // - Save excel file without ever making it visible if filepath is given
    // - Don't save excel file, just make it visible if no filepath is given
    public static void ExportToExcel(this DataTable tbl, string excelFilePath = null) {
        try {
            if (tbl == null || tbl.Columns.Count == 0)
                throw new Exception("ExportToExcel: Null or empty input table!\n");

            // load excel, and create a new workbook
            var excelApp = new Excel.Application();
            excelApp.Workbooks.Add();

            // single worksheet
            Excel._Worksheet workSheet = excelApp.ActiveSheet;

            // column headings
            for (var i = 0; i < tbl.Columns.Count; i++) {
                workSheet.Cells[1, i + 1] = tbl.Columns[i].ColumnName;
            }

            // rows
            for (var i = 0; i < tbl.Rows.Count; i++) {
                // to do: format datetime values before printing
                for (var j = 0; j < tbl.Columns.Count; j++) {
                    workSheet.Cells[i + 2, j + 1] = tbl.Rows[i][j];
                }
            }

            // check file path
            if (!string.IsNullOrEmpty(excelFilePath)) {
                try {
                    workSheet.SaveAs(excelFilePath);
                    excelApp.Quit();
                    MessageBox.Show("Excel file saved!");
                }
                catch (Exception ex) {
                    throw new Exception("ExportToExcel: Excel file could not be saved! Check filepath.\n"
                                        + ex.Message);
                }
            } else { // no file path is given
                excelApp.Visible = true;
            }
        }
        catch (Exception ex) {
            throw new Exception("ExportToExcel: \n" + ex.Message);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这需要安装Excel. (17认同)
  • `ExcelFilePath!= null && ExcelFilePath!=""`可能是`!String.IsNullOrEmpty(ExcelFilePath)` (4认同)
  • 另一个注意事项:Microsoft不建议在服务器上使用Interop https://support.microsoft.com/en-us/help/257757/considerations-for-server-side-automation-of-office (2认同)

小智 20

解决方案基于tuncalik(感谢您的想法)文章,但在大表的情况下工作更快(并且不太清楚).

public static class My_DataTable_Extensions
{
    /// <summary>
    /// Export DataTable to Excel file
    /// </summary>
    /// <param name="DataTable">Source DataTable</param>
    /// <param name="ExcelFilePath">Path to result file name</param>
    public static void ExportToExcel(this System.Data.DataTable DataTable, string ExcelFilePath = null)
    {
        try
        {
            int ColumnsCount;

            if (DataTable == null || (ColumnsCount = DataTable.Columns.Count) == 0)
                throw new Exception("ExportToExcel: Null or empty input table!\n");

            // load excel, and create a new workbook
            Microsoft.Office.Interop.Excel.Application Excel = new Microsoft.Office.Interop.Excel.Application();
            Excel.Workbooks.Add();

            // single worksheet
            Microsoft.Office.Interop.Excel._Worksheet Worksheet = Excel.ActiveSheet;

            object[] Header = new object[ColumnsCount];

            // column headings               
            for (int i = 0; i < ColumnsCount; i++)
                Header[i] = DataTable.Columns[i].ColumnName;

            Microsoft.Office.Interop.Excel.Range HeaderRange = Worksheet.get_Range((Microsoft.Office.Interop.Excel.Range)(Worksheet.Cells[1, 1]), (Microsoft.Office.Interop.Excel.Range)(Worksheet.Cells[1, ColumnsCount]));
            HeaderRange.Value = Header;
            HeaderRange.Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.LightGray);
            HeaderRange.Font.Bold = true;

            // DataCells
            int RowsCount = DataTable.Rows.Count;
            object[,] Cells = new object[RowsCount, ColumnsCount];

            for (int j = 0; j < RowsCount; j++)
                for (int i = 0; i < ColumnsCount; i++)
                    Cells[j, i] = DataTable.Rows[j][i];

            Worksheet.get_Range((Microsoft.Office.Interop.Excel.Range)(Worksheet.Cells[2, 1]), (Microsoft.Office.Interop.Excel.Range)(Worksheet.Cells[RowsCount + 1, ColumnsCount])).Value = Cells;

            // check fielpath
            if (ExcelFilePath != null && ExcelFilePath != "")
            {
                try
                {
                    Worksheet.SaveAs(ExcelFilePath);
                    Excel.Quit();
                    System.Windows.MessageBox.Show("Excel file saved!");
                }
                catch (Exception ex)
                {
                    throw new Exception("ExportToExcel: Excel file could not be saved! Check filepath.\n"
                        + ex.Message);
                }
            }
            else    // no filepath is given
            {
                Excel.Visible = true;
            }
        }
        catch (Exception ex)
        {
            throw new Exception("ExportToExcel: \n" + ex.Message);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这是我尝试过的最快的样本,干得好。之后我不得不使用 Marshal 来发布文件。`Excel.退出(); Marshal.FinalReleaseComObject(Worksheet); Marshal.FinalReleaseComObject(HeaderRange); Marshal.FinalReleaseComObject(Excel);` (2认同)

May*_*rad 13

尝试此函数传递要导出的数据表和文件路径

public void CreateCSVFile(ref DataTable dt, string strFilePath)
{            
    try
    {
        // Create the CSV file to which grid data will be exported.
        StreamWriter sw = new StreamWriter(strFilePath, false);
        // First we will write the headers.
        //DataTable dt = m_dsProducts.Tables[0];
        int iColCount = dt.Columns.Count;
        for (int i = 0; i < iColCount; i++)
        {
            sw.Write(dt.Columns[i]);
            if (i < iColCount - 1)
            {
                sw.Write(",");
            }
        }
        sw.Write(sw.NewLine);

        // Now write all the rows.

        foreach (DataRow dr in dt.Rows)
        {
            for (int i = 0; i < iColCount; i++)
            {
                if (!Convert.IsDBNull(dr[i]))
                {
                    sw.Write(dr[i].ToString());
                }
                if (i < iColCount - 1)
                {
                    sw.Write(",");
                }
            }

            sw.Write(sw.NewLine);
        }
        sw.Close();
    }
    catch (Exception ex)
    {
        throw ex;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这不会真正使用 Excel 文档中的表格单元格,而是每行的所有内容都将打印在每行的第一个单元格上。 (2认同)

Nit*_*ran 6

使用DocumentFormat.OpenXmlnuget 包,我创建了一个单例类,它处理从 aDataTableDataSet. 表格将在工作簿中表示为单独的工作表。

主要类

public sealed class OfficeOpenXML
    {
        private static Lazy<OfficeOpenXML> _instance = new Lazy<OfficeOpenXML>(() => new OfficeOpenXML());
        private OfficeOpenXML()
        {

        }
        public static OfficeOpenXML GetInstance()
        {
            return _instance.Value;
        }

        public MemoryStream GetExcelStream(DataSet ds, bool firstRowAsHeader = false)
        {
            if (ds == null || ds.Tables.Count == 0)
            {
                return null;
            }

            MemoryStream stream = new MemoryStream();
            using (var excel = SpreadsheetDocument.Create(stream, SpreadsheetDocumentType.Workbook))
            {
                //create doc and workbook
                WorkbookPart workbookPart = excel.AddWorkbookPart();
                Workbook workbook = new Workbook();
                Sheets sheets = new Sheets();
                //loop all tables in the dataset
                for (int iTable = 0; iTable < ds.Tables.Count; iTable++)
                {
                    var table = ds.Tables[iTable];
                    //create sheet part
                    WorksheetPart worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
                    Worksheet worksheet = new Worksheet();
                    SheetData data = new SheetData();
                    List<Row> allRows = new List<Row>();

                    //setting header of the sheet
                    Row headerRow = new Row() { RowIndex = 1 };
                    for (int iColumn = 0; iColumn < table.Columns.Count; iColumn++)
                    {
                        var col = table.Columns[iColumn];
                        //if first row of table is not the header then set columns of table as header of sheet
                        if (!firstRowAsHeader)
                        {
                            headerRow.Append(new Cell
                            {
                                DataType = CellValues.String,
                                CellValue = new CellValue(col.ColumnName)
                            });
                        }
                        else
                        {
                            headerRow.Append(new Cell
                            {
                                DataType = CellValues.String,
                                CellValue = new CellValue(Convert.ToString(table.Rows[0][col]))
                            });
                        }
                    }
                    allRows.Add(headerRow);

                    //setting other data rows
                    if (table.Rows != null && table.Rows.Count != 0)
                    {
                        for (int iRow = firstRowAsHeader ? 1 : 0; iRow < table.Rows.Count; iRow++)
                        {
                            var row = table.Rows[iRow];
                            Row valueRow = new Row { RowIndex = (uint)(iRow + (firstRowAsHeader ? 1 : 2)) };

                            for (int iColumn = 0; iColumn < table.Columns.Count; iColumn++)
                            {
                                var col = table.Columns[iColumn];
                                valueRow.Append(new Cell
                                {
                                    DataType = Format(col.DataType),
                                    CellValue = new CellValue(Convert.ToString(row[col]))
                                });
                            }
                            allRows.Add(valueRow);
                        }
                    }

                    //add rows to the data
                    data.Append(allRows);
                    worksheet.Append(data);
                    worksheetPart.Worksheet = worksheet;
                    worksheetPart.Worksheet.Save();

                    //add worksheet to main sheets
                    sheets.Append(new Sheet
                    {
                        Name = string.IsNullOrWhiteSpace(table.TableName) ? "Sheet" + (iTable + 1) : table.TableName,
                        Id = workbookPart.GetIdOfPart(worksheetPart),
                        SheetId = (uint)iTable + 1
                    });
                }//single table processing ends here

                //add created sheets to workbook
                workbook.Append(sheets);
                excel.WorkbookPart.Workbook = workbook;
                excel.WorkbookPart.Workbook.Save();


                excel.Close();
            }
            stream.Seek(0, SeekOrigin.Begin);  
            stream.Capacity = (int)stream.Length;  
            return stream;


        }
        public MemoryStream GetExcelStream(DataTable dt, bool firstRowAsHeader = false)
        {
            DataSet ds = new DataSet();
            ds.Tables.Add(dt);
            return GetExcelStream(ds, firstRowAsHeader);
        }



        #region Excel Helpers

        CellValues Format(Type t)
        {

            switch (t.ToString())
            {

                case "System.String":
                    return CellValues.String;
                case "System.DateTime":
                    return CellValues.Date;
                case "System.Boolean":
                    return CellValues.Boolean;
                case "System.Int16":
                    return CellValues.Number;
                case "System.Int32":
                    return CellValues.Number;
                case "System.Int64":
                    return CellValues.Number;
                case "System.UInt16":
                    return CellValues.Number;
                case "System.UInt32":
                    return CellValues.Number;
                case "System.UInt64":
                    return CellValues.Number;
                case "System.Decimal":
                    return CellValues.Number;
                case "System.Double":
                    return CellValues.Number;
                case "System.Single":
                    return CellValues.Number;
                default:
                    return CellValues.String;
            }
        }
        #endregion
    }
Run Code Online (Sandbox Code Playgroud)

保存到文件

        var excelApp = OfficeOpenXML.GetInstance();
        var dt = GetDataTableFromDB();
        using (var stream = excelApp.GetExcelStream(dt, false))//use true to hide datatable columns from excel
        {

            using (FileStream fs = new FileStream(@"C:\Users\Public\myexcel.xlsx", FileMode.Create))
            {
                stream.CopyTo(fs);
                fs.Flush();
            }
        }
Run Code Online (Sandbox Code Playgroud)

在 MVC 应用程序中下载

public ActionResult DownloadReport()
{
    var ds = GetDataSetFromDB();
    var excelApp = OfficeOpenXML.GetInstance();
    var file = excelApp.GetExcelStream(ds, false);
    return File(file, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", Guid.NewGuid().ToString() + ".xlsx");
}
Run Code Online (Sandbox Code Playgroud)


Tim*_*Tim 5

最好,最简单的方法

private void exportToExcel(DataTable dt)
    {

        /*Set up work book, work sheets, and excel application*/
        Microsoft.Office.Interop.Excel.Application oexcel = new Microsoft.Office.Interop.Excel.Application();
        try
        {
            string path = AppDomain.CurrentDomain.BaseDirectory;
            object misValue = System.Reflection.Missing.Value;
            Microsoft.Office.Interop.Excel.Workbook obook = oexcel.Workbooks.Add(misValue);
            Microsoft.Office.Interop.Excel.Worksheet osheet = new Microsoft.Office.Interop.Excel.Worksheet();


          //  obook.Worksheets.Add(misValue);

            osheet = (Microsoft.Office.Interop.Excel.Worksheet)obook.Sheets["Sheet1"];
            int colIndex = 0;
            int rowIndex = 1;

            foreach (DataColumn dc in dt.Columns)
            {
                colIndex++;
                osheet.Cells[1, colIndex] = dc.ColumnName;
            }
            foreach (DataRow dr in dt.Rows)
            {
                rowIndex++;
                colIndex = 0;

                foreach (DataColumn dc in dt.Columns)
                {
                    colIndex++;
                    osheet.Cells[rowIndex, colIndex] = dr[dc.ColumnName];
                }
            }

            osheet.Columns.AutoFit();
            string filepath = "C:\\Temp\\Book1";

            //Release and terminate excel

            obook.SaveAs(filepath);
            obook.Close();
            oexcel.Quit();
            releaseObject(osheet);

            releaseObject(obook);

            releaseObject(oexcel);
            GC.Collect();
        }
        catch (Exception ex)
        {
            oexcel.Quit();
            log.AddToErrorLog(ex, this.Name);
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • `private void releaseObject(object o) { try { while (System.Runtime.InteropServices.Marshal.ReleaseComObject(o) &gt; 0) { } } catch { } finally { o = null; } }` (2认同)

Rom*_*lko 5

您可以使用我的SwiftExcel库。当它直接将数据写入文件时,它在性能和内存使用率低的情况下特别好:

using (var ew = new ExcelWriter("C:\\temp\\test.xlsx"))
{
    for (var row = 1; row <= 100; row++)
    {
        for (var col = 1; col <= 10; col++)
        {
            ew.Write($"row:{row}-col:{col}", col, row);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

安装 Nuget 命令:

Install-Package SwiftExcel
Run Code Online (Sandbox Code Playgroud)