假设:
override object RequestComAddInAutomationService()
,它返回一个在我的场景中被称为Facade
的类的实例。AddIn.Object
以获取Facade并使用它。更新:原来这是一个有问题的特定用户。她总是拥有它,其他人从来没有它(?永远不会说“从不”)
在这“偶尔”中,我得到了
错误:对象变量或未设置块变量
在尝试访问Facade
属性的代码行中。简而言之,我可以告诉你,RequestComAddInAutomationService()
中的代码中没有任何容易出错的魔法,并且访问加载项的VBA代码也是从网上获取的,看起来也很好。对于那些花时间阅读它的人来说,还有更长的版本: - )
问题:有没有人知道为什么会发生这种情况?这是Excel问题吗?
承诺的细节:
MyAddIn.cs:
public partial class MyAddIn
{
public Facade Facade { get; private set; }
protected override object RequestComAddInAutomationService()
{
if (this.Facade == null)
this.Facade = new Facade(Controller.Instance);
return this.Facade;
}
}
Facade.cs:
[ComVisible(true)]
[Guid("1972781C-A71A-48cd-9675-AE47EACE95E8")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IFacade
{
// some methods
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public class Facade : IFacade
{
private Controller Controller { get; set; }
public Facade(Controller controller)
{
this.Controller = controller;
}
}
Facade
有一些方法,但没有一个字段。
Controller.cs:
public class Controller
{
private static Controller instance = null;
public static Controller Instance
{
get
{
if (instance == null) instance = new Controller();
return instance;
}
}
private Controller() { }
}
Controller
有一些私人字段。由于字段分配是在创建时执行的,因此我对它们进行了审核。它们中的大多数都没有初始化,或者它们设置为null
,因此构造函数几乎没有任何作用。
VBA代码:
Dim addin As Office.COMAddIn
Dim automationObject As Object
Set addin = Application.COMAddIns("My AddIn")
Set automationObject = addin.Object
Dim oResult As Object
Set oResult = automationObject.SomeMethodThatReturnsAnObject()
最后一行是错误发生的地方。虽然调用的方法返回一个对象,但我很确定它不能成为错误的来源:如果返回的引用是null
,那么该语句只会求值为Set oResult = Nothing
,它仍然有效。每当在Nothing
的引用上执行方法时,VBA就会抛出此类错误,在我的情况下为automationObject
。
另一方面,如果加载项根本不存在,Application.COMAddIns(...)
会引发索引超出范围错误,我之前已经看到过。< / p>
答案 0 :(得分:3)
大部分时间工作并且失败有时看起来像是竞争条件。 Andrew Whitechapel撰写了与RequestComAddInAutomationService
1 相关的竞争条件:
<强> COMAddIns Race Condition 强>
尽管他说竞争条件不应该是进程内VBA宏的问题,但问题可能发生在您的特定情况中。
尝试建议的解决方法并循环,直到Addin.Object
有效(C#代码,类似于VBA):
while (utils == null)
{
utils = (ComServiceOleMarshal.IAddinUtilities)addin.Object;
System.Threading.Thread.Sleep(100);
}
utils.DoSomething();
1 关于你正在做的事情,他的博客上有很多有用的信息,所以千万不要错过相关的文章。
答案 1 :(得分:2)
原来Excel禁用了COM加载项。众所周知,这种情况有时是无声的,没有Excel抱怨任何事情。
因此,由于加载项已在excel中注册,因此以下行成功:
Set addin = Application.COMAddIns("My AddIn")
但由于它被禁用,因此未创建对象
Set automationObject = addin.Object
导致Nothing
。
答案 2 :(得分:1)
我遇到了类似的问题,经常但并非总是如此,所以我不能肯定地说,但似乎解决它的事情是项目/应用程序/装配信息......并检查Make assembly COM-可见,然后使用:
创建对象(在Excel VBA中)Set automationObject = CreateObject("PlugInDllName.PlugInClass")
没有问题 - 手指交叉。