【问题标题】:Improve performance of Excel file creation提高 Excel 文件创建的性能
【发布时间】:2016-01-22 11:49:10
【问题描述】:

我有一个带有TabControl 的应用程序。它有一些TabPages,都有一个DataGridView,里面填满了DataTable
一旦TabControl 被填满,我希望能够将所有DataGridViews(或者更确切地说是它们的DataSources,它们都是DataTables)导出到一个Excel 文件中。
我有以下代码。它可以工作,但需要将近一分钟。

按钮被点击:

private void exportBtn_Click(object sender, EventArgs e)
{
    var result = new List<DataTable>();
    foreach (TabPage page in tabControl1.TabPages)
    {
        var dgv = page.Controls[0] as DataGridView;
        if (dgv == null) continue;
        
        var dt = dgv.DataSource as DataTable;
        if (dt == null) continue;
        dt.TableName = page.Text;

        result.Add(dt);
    }

    ExportServices.ToExcel(result);
}

ExportServices 如下所示:

internal static class ExportServices
{
    public static void ToExcel(List<DataTable> tables)
    {
        var excelApp = new Microsoft.Office.Interop.Excel.Application();
        excelApp.Workbooks.Add();

        foreach (var table in tables)
        {
            table.AddSheetToExcelApp(excelApp);
        }
        excelApp.Visible = true;
    }
}

DataTable的扩展方法,取自this question

public static void AddSheetToExcelApp(this DataTable Tbl, Microsoft.Office.Interop.Excel.Application excelApp)
{
    try
    {
        if (Tbl == null || Tbl.Columns.Count == 0)
            throw new Exception("ExportToExcel: Null or empty input table!\n");

        // single worksheet
        _Worksheet workSheet = (_Worksheet)excelApp.Sheets.Add();
        workSheet.Name = Tbl.TableName.Remove(5,1);

        // column headings
        for (int i = 0; i < Tbl.Columns.Count; i++)
        {
            workSheet.Cells[1, (i + 1)] = Tbl.Columns[i].ColumnName;
        }
        // rows
        for (int i = 0; i < Tbl.Rows.Count; i++)
        {
            for (int j = 0; j < Tbl.Columns.Count; j++)
            {
                workSheet.Cells[(i + 2), (j + 1)] = Tbl.Rows[i][j];
            }
        }
    }
    catch (Exception ex)
    {
        throw new Exception("ExportToExcel: \n" + ex.Message);
    }
}

正如我所说,这段代码有效。但这样做需要很长时间。在随机时间暂停程序的执行向我表明,大部分时间它都在// rows下面的循环中工作。
有什么办法可以加速这个?用户等待一分钟来获取一个 Excel 文件真的不会很有趣。

编辑: 忘了提到我不能使用除了我已安装的库之外的任何其他库。我们公司正在处理非常敏感的数据,因此我们不允许运行来自“外部世界”的任何代码。

【问题讨论】:

  • 根据我使用excel interop 的经验,使用单元格范围而不是单个单元格会更快。我建议从链接的问题中尝试这个答案stackoverflow.com/a/21079709/1506454;如果范围太大,请尝试为每一行创建范围,例如

标签: c# excel winforms performance iteration


【解决方案1】:

一个一个地设置单元格是非常低效的。我建议你一次设置整张桌子:

object[,] array = new object[Tbl.Rows.Count,Tbl.Columns.Count]
// Fill the array with values then

workSheet.Range[workSheet.Cells[1, 1], workSheet.Cells[Tbl.Rows.Count, Tbl.Columns.Count]].Value = array;

或者,至少,使用更大的碎片。

【讨论】:

  • 时间从 56 秒减少到
【解决方案2】:

使用 COM dll 转 Excel 需要时间是正常的

试试这个。你不需要机器上的excel。我测试并使用这种方法将数据导出到 excel 1 000 000 行

https://github.com/jsegarra1971/SejExcelExport

如何使用它的完整示例:

http://www.codeproject.com/Tips/829389/Fast-Excel-Import-and-Export

【讨论】:

    【解决方案3】:

    随着时间的推移,我使用了三种方法:

    1) 写出一个 csv 文件,然后将其导入到 excel 工作表中。

    2) 将数据放入剪贴板,用制表符分隔值,然后将其粘贴到 Excel 中(可能使用特殊粘贴 -> 无格式)。能否做到这一点显然很大程度上取决于程序运行的环境。

    3) 了解和使用 OpenXmlWriter。这比任何其他选项都灵活得多,但也有相当长的学习曲线才能做到正确。

    【讨论】:

      【解决方案4】:

      您可以在不执行 Excel 应用程序的情况下生成 Excel 文件 您可以使用EPPlus library。这是一个功能丰富的成熟库

      【讨论】:

      • 谢谢,在寻找导出方式时,我也遇到了这个问题。但正如我在编辑中提到的,我不能使用第三方库。
      • 我后来看到了你的限制。在这种情况下,最好的解决方案来自@AlexButenko。但我总是将行设置为制表符分隔的字符串
      猜你喜欢
      • 2014-08-24
      • 1970-01-01
      • 2021-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-22
      • 1970-01-01
      相关资源
      最近更新 更多