早上好,研究员们:
我目前正在尝试修复从以前的开发人员继承的Excel共享加载项的几个性能问题,基本上我正在尝试查找加载项内部如何在Excel内部工作,这意味着我已经搜索了网络我的理解是:
现在我将Log4Net添加到加载项中,奇怪的是我已经看到了以下行为
在Excel工作簿的打开事件期间,有一个全局变量
Public myAddin As Object
Set myAddin = New TradingAddin.TradingAddin
因此调用C#类的Contructor。
几秒钟后,再次调用构造函数,并按预期调用所有IDTExtensibility2方法OnConnection,OnDisconnection等。
我认为一旦Excel加载外接程序,它应该可用于VBE代码,我可以编写类似
的内容Set myAddin = Application.COMAddins.Item("Trading").Object
但它返回Nothing并且调用Class的Constructor两次销毁在Excel工作簿的生命周期内应该在内存中可用的C#Object内保存的任何状态。
更新:
平台是Visual Studio 2005 Team Edition,目标应用程序是Excel 2003,加载项是共享加载项。我没有使用VSTO。
我试图在VBA中调用的实际代码是
Set addIn = Application.COMAddIns.Item("K2Trading.K2Trading").Connect
Set managedObject3 = addIn.Object <--- This value that I thought was an Instance of the Add-in is equal to Nothing (NULL)
Set addIn = Application.COMAddIns("K2Trading.K2Trading").Connect
同样,将注册表中的LoadBehaviour更改为3,从第一次正确触发所有可扩展性事件OnConnection,OnDisconecction和Object Class构造函数时加载外接程序,现在我需要从VBA中找到一种调用VBA的方法。加载项,意味着如何将加载项实例连接到VBA中的引用,并从那里调用通过COM对象的接口公开的所有方法????
我还使用ProcMon进行了双重检查,发现加载项已被Excel发现并按照此链接加载(非常有用)http://blogs.msdn.com/dvespa/archive/2008/10/15/troubleshooting-outlook-com-addins-using-procmon.aspx。
我们的任何想法或许指向正确的方向?
我怎样才能知道加载了多少个COM对象实例?或者换成另一个单词可以有一个COM对象的单个实例吗?
TIA, 佩德罗
致迈克:
我尝试了你的解决方案但我在执行此代码时遇到了未指定的错误(HRESULT异常:0x80004005(E_FAIL))
public void OnConnection(object application, Extensibility.ext_ConnectMode connectMode,
object addInInst, ref System.Array custom)
{
object missing = System.Reflection.Missing.Value;
try
{
if (debug)
{
log.Debug("Connection Mode :" + connectMode);
}
this.excelApp = (Excel.Application)application;
this.addInInstance = addInInst;
Office.COMAddIn addIn = this.excelApp.COMAddIns.Item(ref addInInst);
//addIn.Object = this;
// We connect our Instance of the Add-in to the Arrya of COMAddins of Excel
VBA.Interaction.CallByName(addIn, "Object", VBA.CallType.Let, this);
^
|
The Exception occurs here.
您会注意到这与您之前发布的内容略有不同
public void OnConnection(
object application,
Extensibility.ext_ConnectMode connectMode,
object addInInst,
ref System.Array custom)
{
// Direct call fails b/c ".Object" is a late-bound call:
//
// addInInst.Object = this;
// Reflection fails I believe b/c .Object is a 'let' assigned
// property for reference type, which is very unusual even for
// COM (although legal) and is a foreign concept to .NET. Use
// of the right BindingFlags here *might* work, but I'm not sure:
//
// PropertyInfo propInfo;
// propInfo = addInInst.GetType().GetProperty("Object");
// propInfo.SetValue(addInInst, this, null);
// This works!:
VBA.Interaction.CallByName(addInInst, "Object", VBA.CallType.Let, this);
}
因为addInInst不是作为Office.COMAddin传递的,而是我的类的实例,所以 尝试分配给Object属性是不正确的,因为它在该类
中不存在另外我很好奇Excel如何加载加载项,我的意思是基于我刚刚加载Excel时的观察,OnConnection方法没有立即执行,但直到我点击= AvgCost( )功能??
有什么想法吗?
答案 0 :(得分:2)
我怎么能知道有多少 COM对象的实例是 装?或换句话说 可能有一个单一的 COM对象的实例?
你的意思是COM插件吗?您不能多次将相同的COM加载项加载到Excel中。
现在我需要找到一种方法 来自VBA的调用部分 加载项,意思是如何连接 加载项实例到VBA中的引用 那里召唤所有的方法 通过接口暴露出来 COM对象????
VBA都是后期绑定的,它没有预先编译成像VB6 DLL或.NET程序集这样的DLL。因此,您的所有VBA调用也必须延迟绑定。最简单的方法是调用Excel.Appliction.Run("NameOfYourVbaMacro")
来调用工作簿中标准模块中存储的任何宏。 (您可以使用Excel.Application.Workbooks["NameOfYourAddin.xla"]
按名称访问工作簿。除了强制加载外,您不需要将其视为加载项。)您还可以使用反射代码访问工作簿和工作表成员,如果您在ThisWorkbook
类模块或任何Worksheet
类模块后面有代码。
我认为一旦Excel加载了 加载项应该可用于 VBE代码,我可以写点东西 像
设置myAddin = Application.COMAddins.Item( “交易”)。对象
因此,如果我理解正确,您不仅希望拥有C#托管COM加载项调用VBA代码(如上所述),而且现在您还希望VBA代码能够调用我们的C#托管COM加入?我认为这很复杂,可能需要重新思考......但是可以做到。
从C#完成将您的托管COM加载项通过ComAddin.Object
属性暴露给COM调用者很棘手,但是可行。请参阅以下讨论:
Calling Managed Add-In method from Automation client
我希望这有助于你前进......
麦克
编辑:对Pedro的回复的回复
佩德罗,
你会注意到这看起来很小 不同于你发布了一段时间 前...
是的,您的代码不同,这也是它不起作用的原因!
至少,您的最后一行看起来不正确:
VBA.Interaction.CallByName(addIn, "Object", VBA.CallType.Let, this);
相反,您的代码应该在您的类中传递给'addInInst':
VBA.Interaction.CallByName(addInInst, "Object", VBA.CallType.Let, this);
我不确定你要通过这条线做什么:
Office.COMAddIn addIn = this.excelApp.COMAddIns.Item(ref addInInst);
该行看起来应该抛出异常。我很惊讶它没有。但是代码类似于您传入要访问的COM加载项的progId的代码 - 通常由希望通过.Object属性访问COM加载项的外部调用者使用。这不是应该从 加载项本身使用的代码。
因为addInInst没有作为传递 Office.COMAddin但是我的一个实例 类,所以试图分配给 对象属性不正确,因为它 该类中不存在
我不明白你在这里要做什么。我不知道你是否可以传入除实现IDTExtensibility2的类的实例之外的任何其他对象。至少,通过使用正确的类和接口属性,您传回的任何类必须成为COM可见类。但我认为坚持从OnConnection方法中传入实现IDTExtensibility2的类的标准做法要容易得多。也就是说,传递你的'this'对象参考。
如果你想尝试超越标准方法的花哨的东西,那没关系,但我会先得到一个简单的例子。尝试复制我在示例Calling Managed Add-In method from Automation client中显示的代码。一旦你有了这个工作,你可以尝试进行更复杂的操作。但是一旦你有简单的版本工作,我想你会发现这就是你所需要的。
我希望这有助于佩德罗,
麦克