在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来运行计算。 请注意,您不能从
BackgroundWorker
的DoWork
事件处理程序访问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操作将会相当容易。