代码之家  ›  专栏  ›  技术社区  ›  chiccodoro

vba:addin.object中的vsto有时不返回任何值(空)

  •  3
  • chiccodoro  · 技术社区  · 14 年前

    鉴于:

    • VSTO加载项
    • override object RequestComAddInAutomationService() 它返回调用的类的实例 Facade 在我的场景中。
    • Excel2007中访问 AddIn.Object 以获得正面并使用它。
    • 很多时候,这种方法都非常有效。
    • 有几次,突然间,这似乎不起作用。

    更新:结果发现是某个特定的用户有问题。她一直都有,别人从来没有。从不说“从不”)。

    在这“几次”中我得到

    错误:未设置对象变量或WITH块变量

    在试图访问的属性的代码行 外观 . 简而言之,我可以告诉你 RequestComAddInAutomationService() 它没有任何容易出错的魔力,而且用于访问外接程序的VBA代码已经从Web上获取,看起来也很好。对于那些需要花时间阅读的人来说,更长的版本还没有到来:—)

    问题:有人知道为什么会发生这种情况吗?这是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;
        }
    }
    

    立面.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;
        }
    }
    

    外观 有一些方法,但不是单个字段。

    控制器:

    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()
    

    最后一行是错误发生的地方。尽管调用的方法返回一个对象,但我确信它不能是错误的根源:如果返回的引用是 无效的 ,则该语句将简单地计算为 Set oResult = Nothing 仍然有效。每当对引用执行的方法 Nothing ,即 automationObject 就我而言。

    另一方面,如果加载项根本不存在,则 Application.COMAddIns(...) 会提高 索引越界 错误,我以前见过。

    3 回复  |  直到 8 年前
        1
  •  3
  •   Dirk Vollmar    14 年前

    RequestComAddInAutomationService :

    COMAddIns Race Condition

    尽管他说竞争条件不应该是进程内VBA宏的问题,但问题可能发生在您的特定场景中。

    Addin.Object 有效(C代码,类似于VBA):

    while (utils == null)
    {
        utils = (ComServiceOleMarshal.IAddinUtilities)addin.Object;
        System.Threading.Thread.Sleep(100);
    }    
    utils.DoSomething();
    

    他的博客上有很多关于你所做事情的有用信息,所以不要错过相关的文章。

        2
  •  2
  •   chiccodoro    14 年前

    原来Excel禁用了COM加载项。这是众所周知的,有时会发生沉默,没有Excel抱怨任何事情。

    因此,由于外接程序已注册到Excel,因此以下行成功:

    Set addin = Application.COMAddIns("My AddIn")
    

    Set automationObject = addin.Object
    

    导致 Nothing .

        3
  •  1
  •   Tony Delroy    12 年前

    我也遇到过类似的问题,通常但并非总是如此,所以我不能肯定地说,但似乎能解决问题的事情是将其提交给项目/应用程序/程序集信息…选中“使程序集COM可见”,然后使用以下命令创建对象(在Excel VBA中):

    Set automationObject = CreateObject("PlugInDllName.PlugInClass")
    

    从那以后就没问题了。