【问题标题】:Most efficient way to export DataTable to Excel File (.xlsx) [closed]将 DataTable 导出到 Excel 文件(.xlsx)的最有效方法 [关闭]
【发布时间】:2017-07-15 04:24:24
【问题描述】:

我想知道在速度方面将 DataTable 或 DataSet 导出到 .xlsx 文件的最有效方法是什么。

我有 200K 行的表,循环是没用的,所以我想做一个批量导出或类似的东西。

有什么容易实现的回答我的问题吗?

解决方案: 如果有人需要,我终于通过这种方式使用了 OpenXml。它在大约 1 分钟内导出 100k:

    private void ExportDataSet(DataSet ds, string destination)
    {
        using (var workbook = SpreadsheetDocument.Create(destination, DocumentFormat.OpenXml.SpreadsheetDocumentType.Workbook))
        {
            var workbookPart = workbook.AddWorkbookPart();

            workbook.WorkbookPart.Workbook = new DocumentFormat.OpenXml.Spreadsheet.Workbook();

            workbook.WorkbookPart.Workbook.Sheets = new DocumentFormat.OpenXml.Spreadsheet.Sheets();

            foreach (System.Data.DataTable table in ds.Tables)
            {

                var sheetPart = workbook.WorkbookPart.AddNewPart<WorksheetPart>();
                var sheetData = new DocumentFormat.OpenXml.Spreadsheet.SheetData();
                sheetPart.Worksheet = new DocumentFormat.OpenXml.Spreadsheet.Worksheet(sheetData);

                DocumentFormat.OpenXml.Spreadsheet.Sheets sheets = workbook.WorkbookPart.Workbook.GetFirstChild<DocumentFormat.OpenXml.Spreadsheet.Sheets>();
                string relationshipId = workbook.WorkbookPart.GetIdOfPart(sheetPart);

                uint sheetId = 1;
                if (sheets.Elements<DocumentFormat.OpenXml.Spreadsheet.Sheet>().Count() > 0)
                {
                    sheetId =
                        sheets.Elements<DocumentFormat.OpenXml.Spreadsheet.Sheet>().Select(s => s.SheetId.Value).Max() + 1;
                }

                DocumentFormat.OpenXml.Spreadsheet.Sheet sheet = new DocumentFormat.OpenXml.Spreadsheet.Sheet() { Id = relationshipId, SheetId = sheetId, Name = table.TableName };
                sheets.Append(sheet);

                DocumentFormat.OpenXml.Spreadsheet.Row headerRow = new DocumentFormat.OpenXml.Spreadsheet.Row();

                List<String> columns = new List<string>();
                foreach (System.Data.DataColumn column in table.Columns)
                {
                    columns.Add(column.ColumnName);

                    DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell();
                    cell.DataType = DocumentFormat.OpenXml.Spreadsheet.CellValues.String;
                    cell.CellValue = new DocumentFormat.OpenXml.Spreadsheet.CellValue(column.ColumnName);
                    headerRow.AppendChild(cell);
                }


                sheetData.AppendChild(headerRow);

                foreach (System.Data.DataRow dsrow in table.Rows)
                {
                    DocumentFormat.OpenXml.Spreadsheet.Row newRow = new DocumentFormat.OpenXml.Spreadsheet.Row();
                    foreach (String col in columns)
                    {
                        DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell();
                        cell.DataType = DocumentFormat.OpenXml.Spreadsheet.CellValues.String;
                        cell.CellValue = new DocumentFormat.OpenXml.Spreadsheet.CellValue(dsrow[col].ToString()); //
                        newRow.AppendChild(cell);
                    }

                    sheetData.AppendChild(newRow);
                }

            }
        }
    }

【问题讨论】:

  • 200k 行并没有那么糟糕.. 听起来您认为它会很慢。
  • @BudaGavril 我只想知道方法,而不是线条,我知道如何编程,但可能更容易知道以哪种方式集中注意力。我听说过 OleDb、ADODB、循环,但我只想知道哪个更快
  • @BugFinder 导出 1k 行和 72 个字段,循环它们非常慢,在我的电脑上大约需要 1 分钟,这非常快。我听说过批量导出方法。

标签: c# wpf excel visual-studio-2015 datatable


【解决方案1】:

你一定是在循环遍历记录,这就是它这么慢的原因。

试试这样的。

var lines = new List<string>();

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

var header = string.Join(",", columnNames);
lines.Add(header);

var valueLines = dataTable.AsEnumerable()
                   .Select(row => string.Join(",", row.ItemArray));            
lines.AddRange(valueLines);

File.WriteAllLines("excel.csv",lines);

或者,将 DataTable 转换为 Excel 文件。

XLWorkbook wb = new XLWorkbook();
DataTable dt = GetDataTableOrWhatever();
wb.Worksheets.Add(dt,"WorksheetName");

【讨论】:

    【解决方案2】:

    就我个人而言,我更喜欢 Syncfusion 的 Excel 库,因为它非常直观、有据可查并且通过社区许可免费。

    你可以在这里下载:XlsIO Product Page

    文档可以在这里找到:XlsIO Documentation

    如果您申请免费社区许可证,则可以免费使用。

    这是一个将 DataTable 写入 xlsx 文件的代码示例。我不认为你的表的大小应该是一个问题,但我不是 100% 确定,我用这个库编写的最大文件有大约 90k 行和 60 列,我没有任何问题。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Data;
    using Syncfusion.XlsIO;
    namespace ConsoleApp3
    {
        class Program
        {
            static void Main(string[] args)
            {
                DataTable Table = new DataTable();
                Table.Columns.Add("Column1");
                Table.Columns.Add("Column2");
                Table.Columns.Add("Column3");
                Table.Rows.Add("Item1", "Item2", "Item3");
    
                ExcelEngine ExcelEngineObject = new Syncfusion.XlsIO.ExcelEngine();
                IApplication Application = ExcelEngineObject.Excel;
                Application.DefaultVersion = ExcelVersion.Excel2013;
                IWorkbook Workbook = Application.Workbooks.Create(1);
                IWorksheet Worksheet = Workbook.Worksheets[0];
                Worksheet.ImportDataTable(Table, true, 1, 1);
                Workbook.SaveAs("YourExcelFile.xlsx");
                Workbook.Close();
                ExcelEngineObject.Dispose();
    
            }
        }
    }
    

    【讨论】:

    • 谢谢,但我投了反对票,因为在我打开保存的电子表格后,那里没有我的任何数据。唯一的东西是一个单元格,上面写着:“使用 Syncfusion Essential XLsIO 的试用版创建”。所以我猜它不起作用和/或不是免费的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-04
    • 1970-01-01
    • 2015-09-27
    • 2016-10-18
    • 1970-01-01
    • 2011-12-12
    相关资源
    最近更新 更多