【问题标题】:VSTO Slow Performance Compared to VBA与 VBA 相比,VSTO 性能较慢
【发布时间】:2012-07-19 21:42:38
【问题描述】:

我是 stackoverflow 的新手,因此我将直接从我的问题开始。

我有几年通过集成 VBA 为 Excel 开发宏的经验,半年前我开始学习新语言 C#。我喜欢它,它的可能性,我还找到了通过 Visual Studio 直接在 C# 中开发 Office 插件的选项(需要 VSTO)。我遇到的问题是,在进行多次测试后,我尝试比较使用 C# 创建的插件和使用 VBA 创建的宏的速度(例如,将字符串“测试字符串”分别粘贴到从 A1 到 A10 000 的每个单元格)。问题是集成的 VBA 比提到的使用 Visual Studio (C#) 创建的插件快几倍。当时我决定不为这个问题而烦恼,但是后来我遇到了同样的问题,但是这次而不是 cca 10 秒(VBA)过程花费了 2 多分钟!

在对谷歌进行研究后,我发现 VSTO 在性能方面并不好,尤其是当您需要您的应用程序与 Excel 交互时(因此有一些方法可以解决该问题,例如将数据保存到动态数组中,然后直接将整个数组填充到活动表中);但是在某些情况下,您只需要与 excel 进行交互(例如我必须动态取消保护工作簿中的许多工作表......在这里您只需说 ActiveSheet.Unprotect)

我对你们的问题是,除了缓慢的 VSTO 之外,还有什么方法可以为 Excel/Word/其他易于部署的 Office 产品创建(可能是其他一些软件)插件? 非常感谢。

问候, 罗伯特

【问题讨论】:

  • “我将直接从我的问题开始。”呃......你有一个有趣的方式直接从这个问题开始。这个问题在最后被隐藏了。
  • 我从“大家好”开始,但由于某种原因它没有显示……也许它会自动过滤“不必要的内容”,以免用户浪费时间:D
  • 我认为除了“本机”VBA 宏之外的任何问题都需要跨越进程边界会产生大量开销:因此在 VSTO 中“批处理”操作(在一次读取整个范围或将数组读取/放入工作表只需要一次调用,而逐个单元格可能需要数千次调用)。
  • 你还没有说为什么你不能使用VBA。
  • 感谢你们这么快的回复!我知道,但正如我所说,在某些情况下您只需要与 Excel 进行交互(正如我所说的取消保护工作簿中的工作表等)。另外@MarkByers我没有说我不能使用VBA,我确实经常使用它,但是当我想创建解决方案/插件并且我想将它重新分发给客户时,它不像通过VSTO那么容易(之后发布给你安装文件,你只需运行它,你不关心其他任何事情)。我不知道如何通过 VBA 做到这一点(自定义功能区面板,以编程方式将代码添加到 PERSONAL.XLS 等)

标签: c# performance excel vba vsto


【解决方案1】:

单独填充 10000 个单元格会让您认为 VSTO 非常慢。使用您提到的动态数组方法,我可以在很短的时间内完成:

static public void PopulateABigNumberOfCells(Excel.Application xlApp, DataTable dataTable)
{
//Turn off Excel updating
SwitchApplicationSettings(xlApp,false);

//Populate a 2D array - via a DataTable in this example
object[,] values = (object[,])Array.CreateInstance(typeof(object), new int[2] { dataTable.Rows.Count, dataTable.Columns.Count }, new int[2] { 1, 1 });
for (int i = 0; i < dataTablea.Rows.Count; i++)
{
 for (int j = 0; j < dataTable.Columns.Count; j++)
 {
  values[i + 1, j + 1] = dataTable.Rows[i][j] == DBNull.Value ? 0 : dataTable.Rows[i][j];
 }
}

//Populate all cells in one swoop 
leftCellNum = XlHelper.ColumnNameToNumber(leftColumn);
string rightBottom = XlHelper.ColumnNumberToName(leftCellNum + dataTable.Columns.Count - 1);
using (var targetRange = xlApp.Range[leftColumn + (startingRow) + ":" + rightBottom + (startingRow + dataTable.Rows.Count - 1)].WithComCleanup())
{
targetRange.Resource.Value2 = values;
}

//Turn on Excel updating
SwitchApplicationSettings(xlApp,true);
}

static public void SwitchApplicationSettings(Excel.Application xlApp, bool on)
{
xlApp.ScreenUpdating = on;
xlApp.DisplayAlerts = on;
xlApp.Calculation = on ? XlCalculation.xlCalculationAutomatic : XlCalculation.xlCalculationManual;;
xlApp.UserControl = on;
xlApp.EnableEvents = on;
}

我使用VSTO Contrib 以获得更好的内存管理。

使用对象模型并不比 VBA 慢 12 倍,除非您专门讨论单独填充数千个单元格。

【讨论】:

    【解决方案2】:

    VSTO-Excel 的性能问题是由于需要在 VBA/VB6 使用的 Excel 的 Com 接口之上添加 Interop 层造成的。所以使用这种方法与 Excel 进行 VSTO 交互总是会很慢。

    可以使用 Excel DNA(免费)和 Addin Express(非免费)等产品在 C# 中使用 XLL 接口。使用这个接口会很快,但比 Com 接口受限。

    以下是用于开发 UDF 的 various technologies 的比较。

    分发 VBA 代码很容易 - 创建一个在应用程序级别运行的插件 (XLA/XLAM),或者分发一个包含嵌入式 VBA 代码的工作簿,用于特定于文档的解决方案。

    【讨论】:

      猜你喜欢
      • 2021-04-02
      • 2019-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-05
      • 2017-08-24
      • 2018-11-17
      相关资源
      最近更新 更多