Microsoft.Office.Interop.Excel太慢了

时间:2018-05-26 13:08:52

标签: c# excel loops office-interop excel-interop

我正在使用Excel Interop,我有一个对象列表。我在循环中的Excel单元格中设置列表中对象的属性时需要很长时间:

- set_fact:
    total: "{{ sum(item | int) }}" <--- it's not work!!!
  loop:
    - 1
    - 4
    - 3
 - debug: var=total

workSheet = (Excel.Worksheet)wbook.ActiveSheet; var row = 1; foreach (var shiftStop in shiftStops) { row++; workSheet.Cells[row, "A"] = shiftStop.MachineName; workSheet.Cells[row, "B"] = shiftStop.MachineType; workSheet.Cells[row, "C"] = shiftStop.UnitName; } 列表包含大约4000个对象。完成返回需要4-5分钟。有没有办法让这个过程更快?

2 个答案:

答案 0 :(得分:2)

执行代码时通常可以关闭以下功能:

  • Application.ScreenUpdating

    关闭屏幕更新。如果Application.ScreenUpdating设置为False,则Excel不会重绘屏幕。当您的代码运行时,屏幕会快速更新,并且用户通常无需查看每个更新。代码执行后,更新屏幕一次,可以提高性能。

  • <强> Application.DisplayStatusBar

    关闭状态栏。如果Application.DisplayStatusBar设置为False,则Excel不会显示状态栏。状态栏设置与屏幕更新设置分开,这样即使屏幕未更新,您仍可以显示当前操作的状态。但是,如果您不需要显示每个操作的状态,则在代码运行时关闭状态栏也可以提高性能。

  • <强> Application.Calculation

    切换到手动计算。如果Application.Calculation设置为xlCalculationManual,则Excel仅在用户明确启动计算时计算工作簿。在自动计算模式下,Excel确定何时计算。例如,每次与公式相关的单元格值更改时,Excel都会重新计算公式。如果将计算模式切换为手动,则可以等到所有与公式关联的单元格都更新后再重新计算工作簿。只需在代码运行时根据需要重新计算工作簿,就可以提高性能。

  • <强> Application.EnableEvents

    关闭活动。如果Application.EnableEvents设置为False,则Excel不会引发事件。如果有加载项侦听Excel事件,那些加载项会在记录事件时消耗计算机上的资源。如果加载项不必记录代码运行时发生的事件,则关闭事件可以提高性能。

  • <强> ActiveSheet.DisplayPageBreaks

    关闭分页符。如果ActiveSheet.DisplayPageBreaks设置为False,则Excel不会显示分页符。在代码运行时没有必要重新计算分页符,并且在代码执行后计算分页符可以提高性能。

Excel performance: Tips for optimizing performance obstructions文章中详细了解相关内容。

另外我建议发布底层的COM对象。所有Excel加载项应在不再需要时系统地释放对Excel对象的引用。未能系统地释放对Excel对象的引用可能会阻止Microsoft Office Excel正常关闭。

完成使用后,使用System.Runtime.InteropServices.Marshal.ReleaseComObject释放Excel对象。然后在Visual Basic中将变量设置为Nothing(C#中为null)以释放对该对象的引用。

答案 1 :(得分:0)

每次在Office应用程序中调用对象时都需要时间 - 尤其是通过互操作。这在您展示的循环操作中尤其明显。

相反,请考虑创建值的ARRAY,然后将数组写入Excel范围。 Excel应该将数组的每个元素写入单元格。这是将大量数据写入Excel以加快处理速度的标准做法。

假设shiftStops是一个数组,代码可能如下所示:

    workSheet = (Excel.Worksheet)wbook.ActiveSheet;
    var row = 1;
    Excel.Range rng = worksheet.Cells[row, "A"];
    rng = rng.Resize(1, shiftStops.Length);
    rng.Value = shiftStops;