在Excel中长时间运行

我有一个Excel电子表格,我有一个.Net库,它做一些相当复杂的calculcations。 .Net程序集通过COM暴露给Excel中的VBA代码。

当我调用.Net库时,Excel UI线程在计算过程中被阻塞。

这可以防止用户与Excel进行交互,并且在某些情况下向用户指示Excel在标题栏中是(Not Responding)。

我不太了解Excel 2010中的VBA,但有什么方法可以在不同的线程中产生对.Net库的调用,并向用户提供“进行中”对话框?

这是可能的,但可能需要一点努力才能把所有东西连接起来。 有很多方法可以解决这个问题,其中一个可能如下所示:

  • VBA在UI线程上调用C#COM对象
  • C#COM对象启动一个BackgroundWorker来运行计算。 请注意,您不能从BackgroundWorkerDoWork事件处理程序访问Excel对象模型。 如果要在计算过程中更新Excel,则BackgroundWorker应使用ReportProgress方法报告UI线程上的进度。
  • ProgressChanged事件处理程序(在UI线程上运行)中,C#代码可以直接更新Excel对象模型,也可以调用VBA代码来执行更新。
  • 在BackgroundWorker运行时,VBA代码可以显示进度对话框,以避免任何重入问题。

有可能是,你不能在C#中使用另一个线程。 Excel是一个单线程应用程序,该线程是UI线程,所以使用Excel的对象模型阻止用户界面。

另一种方法是使用OpenXmlSdk并使用它在一个单独的线程上对Excel数据的副本执行操作,然后重新载入数据。根据数据的大小和计算时间,这可能是值得的。 我在Word中使用了大约100页的文档,并将处理时间从10分钟缩短到<30秒,这30秒中的大部分时间用于从Word导出和导入数据。 Excel在这方面往往会快一点。

使用VBA很难做到,因为Excel VBA几乎是单线程同步的。 但Excel 2010确实支持asynchronousUDF:查看Excel DNA或Addin Express,以获取从.NET执行此操作的一些帮助。
http://exceldna.codeplex.com/wikipage?title=Performing%20Asynchronous%20Work&referringTitle=Documentation
http://www.add-in-express.com/add-in-net/index.php

2 : http : //www.add-in-express.com/add-in-net/index.php
您也可以从基于C的XLL中执行此操作
http://msdn.microsoft.com/en-us/library/office/ff796219%28v=office.14%29.aspx

一个有点疯狂的select(大多数的VBA解决scheme),并没有提到 – 你可以产生dynamic的VBScripts,可以作为一个线程几乎工作,并在后台工作,并将其挂钩到Excel。 我在前面的博客上阅读了这个想法: http : //www.databison.com/index.php/multithreaded-vba-an-approach-to-processing-using-vbscript/

这不是很优雅,但它是一个选项。

你应该使用Excel-dna来做到这一点。 用它来调用asynchronous操作将会相当容易。