代码之家  ›  专栏  ›  技术社区  ›  Duncan Bayne

从VBA访问COM加载项代码

  •  0
  • Duncan Bayne  · 技术社区  · 14 年前

    我使用Visual Studio 2005 Tools for Office创建了一个用于Excel2003的COM加载项。外接程序代码如下所示:

    [guid(“eac0992e-ac39-4126-b851-a57ba3fa80b8”)]
    [可见(真)]
    [程序ID(“nlog4vba.logger”)]
    [类接口(ClassInterfaceType.AutoDual)]
    公共类记录器
    {
    公共双调试(字符串上下文、字符串消息)
    {
    trace.writeline(消息);
    返回消息。长度;
    }
    
    [ComRegisterFunctionAttribute]
    公共静态void寄存器函数(类型类型类型)
    {
    registry.classesroot.createSubkey(getSubKeyName(type,“programmable”));
    registry key key=registry.classesroot.openSubkey(getSubKeyName(type,“inProcServer32”),true);
    key.setvalue(“”,system.environment.systemdirectory+@“\mscoree.dll”,registryvaluekind.string);
    }
    
    [取消注册功能属性]
    公共静态void unregisterfunction(类型类型类型)
    {
    registry.classesroot.deleteSubkey(getSubKeyName(type,“programmable”),false);
    }
    
    私有静态字符串GetSubKeyName(类型类型,字符串SubKeyName)
    {
    system.text.stringbuilder s=新建system.text.stringbuilder();
    s.append(@“clsid \”);
    s.append(type.guid.toString().toUpper());
    s.append(@“\”);
    s.append(子关键字名称);
    返回s.toString();
    }
    }
    < /代码> 
    
    

    我已将项目设置为注册COM互操作,并已将dll注册为:

    regasm.exe/tlb nlog4vba.dll
    < /代码> 
    
    

    打开Excel时,我将转到“工具”->加载项,单击“自动化”,然后添加nlog4vba.logger。然后,我可以转到Insert->函数,从类别列表中选择nlogvba.logger,然后选择Debug。

    最终结果是包含如下内容的单元格:

    =debug(“my context”,“my message”)。
    < /代码> 
    
    

    显示值为:

    < PRE> >代码> 10 < /代码>

    这就是一切。在我的VBA代码中,我可以转到“工具”->引用并添加nlog4vba。然后我将以下代码添加到工作表上的按钮中:

    private sub commandbutton1_click())
    application.comaddins(“nlog4vba.logger”).object.debug“我的上下文”,“我的消息”
    结束子
    < /代码> 
    
    

    这会失败,因为ComAddins(“nlog4vba.logger”)失败的原因是:

    运行时错误“9”:下标超出范围
    < /代码> 
    
    

    有人能告诉我,我需要做什么才能使我的vba代码可以访问debug()方法(这比从单元格中调用该方法更有用)?

    我肯定我这里遗漏了一些简单的东西。

    编辑日期:2010/09/07:我已经更新了代码段,以包含下面Jim建议的[ProgID]属性;问题仍然存在。我可以在注册表中看到该对象:

    [hkey_classes_root\clsid \ eac0992e-ac39-4126-b851-a57ba3fa80b8]
    @=“nlog4vba.logger”(nlog4vba.logger)
    
    [hkey_classes_root\clsid \ eac0992e-ac39-4126-b851-a57ba3fa80b8 \实现的类别]
    
    [hkey_classes_root\clsid \ eac0992e-ac39-4126-b851-a57ba3fa80b8 \实现的类别\ 62c8fe65-4ebb-45e7-b440-6e39b2dbf29]
    
    [hkey_classes_root\clsid \ eac0992e-ac39-4126-b851-a57ba3fa80b8 \inprocserver32]
    @=“C:\\windows\\system32\\mscoree.dll”
    “threadingModel”=“两者”
    “class”=“nlog4vba.logger”类
    “assembly”=“nlog4vba,version=1.0.0.0,culture=neutral,publicKeyToken=null”
    “runtimeversion”=“2.0.50727版”
    “codebase”=“文件:///c:/projects/nlog4vba/nlog4vba/bin/debug/nlog4vba.dll”
    
    [hkey_classes_root\clsid \ eac0992e-ac39-4126-b851-a57ba3fa80b8 \inprocserver32\1.0.0.0]
    “class”=“nlog4vba.logger”类
    “assembly”=“nlog4vba,version=1.0.0.0,culture=neutral,publicKeyToken=null”
    “runtimeversion”=“2.0.50727版”
    “codebase”=“文件:///c:/projects/nlog4vba/nlog4vba/bin/debug/nlog4vba.dll”
    
    [hkey_classes_root\clsid \ eac0992e-ac39-4126-b851-a57ba3fa80b8 progid]
    @=“nlog4vba.logger”(nlog4vba.logger)
    
    [hkey_classes_root\clsid \ eac0992e-ac39-4126-b851-a57ba3fa80b8 \可编程]
    < /代码> 
    
    

    此外,ProgID在“加载项”对话框中可见:

    我仍然不知道这为什么不起作用:—(

    [Guid("EAC0992E-AC39-4126-B851-A57BA3FA80B8")]
    [ComVisible(true)]
    [ProgId("NLog4VBA.Logger")]
    [ClassInterface(ClassInterfaceType.AutoDual)]
    public class Logger
    {
        public double Debug(string context, string message)
        {
            Trace.WriteLine(message);
            return message.Length;
        }
    
        [ComRegisterFunctionAttribute]
        public static void RegisterFunction(Type type)
        {
            Registry.ClassesRoot.CreateSubKey(GetSubKeyName(type, "Programmable"));
            RegistryKey key = Registry.ClassesRoot.OpenSubKey(GetSubKeyName(type, "InprocServer32"), true);
            key.SetValue("", System.Environment.SystemDirectory + @"\mscoree.dll", RegistryValueKind.String);
        }
    
        [ComUnregisterFunctionAttribute]
        public static void UnregisterFunction(Type type)
        {
            Registry.ClassesRoot.DeleteSubKey(GetSubKeyName(type, "Programmable"), false);
        }
    
        private static string GetSubKeyName(Type type, string subKeyName)
        {
            System.Text.StringBuilder s = new System.Text.StringBuilder();
            s.Append(@"CLSID\{");
            s.Append(type.GUID.ToString().ToUpper());
            s.Append(@"}\");
            s.Append(subKeyName);
            return s.ToString();
        }
    }
    

    我已将项目设置为注册COM Interop,并已将DLL注册为:

    regasm.exe /tlb NLog4VBA.dll
    

    打开Excel时,我将转到“工具”->加载项,单击“自动化”,然后添加nlog4vba.logger。然后,我可以转到Insert->函数,从类别列表中选择nlogvba.logger,然后选择Debug。

    最终结果是一个包含如下内容的单元格:

    =Debug("My Context","My Message")
    

    …显示值为:

    10
    

    这就是一切。在我的VBA代码中,我可以转到“工具”->引用并添加nlog4vba。然后我将以下代码添加到工作表上的按钮中:

    Private Sub CommandButton1_Click()
            Application.COMAddIns("NLog4VBA.Logger").Object.Debug "My Context", "My Message"
    End Sub
    

    这会失败,因为ComAddins(“nlog4vba.logger”)在以下情况下失败:

    Run-time error '9': Subscript out of range
    

    有人能告诉我,我需要做什么才能使我的VBA代码可以访问debug()方法(这比从单元格中调用该方法更有用)?

    我肯定我错过了一些简单的东西。

    2010/09/07编辑:我已经更新了代码片段以包含Jim在下面建议的[ProgID]属性;问题仍然存在。我可以在注册表中看到该对象:

    [HKEY_CLASSES_ROOT\CLSID\{EAC0992E-AC39-4126-B851-A57BA3FA80B8}]
    @="NLog4VBA.Logger"
    
    [HKEY_CLASSES_ROOT\CLSID\{EAC0992E-AC39-4126-B851-A57BA3FA80B8}\Implemented Categories]
    
    [HKEY_CLASSES_ROOT\CLSID\{EAC0992E-AC39-4126-B851-A57BA3FA80B8}\Implemented Categories\{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}]
    
    [HKEY_CLASSES_ROOT\CLSID\{EAC0992E-AC39-4126-B851-A57BA3FA80B8}\InprocServer32]
    @="C:\\WINDOWS\\system32\\mscoree.dll"
    "ThreadingModel"="Both"
    "Class"="NLog4VBA.Logger"
    "Assembly"="NLog4VBA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
    "RuntimeVersion"="v2.0.50727"
    "CodeBase"="file:///C:/projects/nlog4vba/NLog4VBA/bin/Debug/NLog4VBA.dll"
    
    [HKEY_CLASSES_ROOT\CLSID\{EAC0992E-AC39-4126-B851-A57BA3FA80B8}\InprocServer32\1.0.0.0]
    "Class"="NLog4VBA.Logger"
    "Assembly"="NLog4VBA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
    "RuntimeVersion"="v2.0.50727"
    "CodeBase"="file:///C:/projects/nlog4vba/NLog4VBA/bin/Debug/NLog4VBA.dll"
    
    [HKEY_CLASSES_ROOT\CLSID\{EAC0992E-AC39-4126-B851-A57BA3FA80B8}\ProgId]
    @="NLog4VBA.Logger"
    
    [HKEY_CLASSES_ROOT\CLSID\{EAC0992E-AC39-4126-B851-A57BA3FA80B8}\Programmable]
    

    此外,ProgID在“加载项”对话框中可见:

    Add-Ins dialog showing ProgID

    我仍然不知道为什么这不起作用:-(

    2 回复  |  直到 14 年前
        1
  •  1
  •   Jim Brissom    14 年前

    ComAddins集合可以通过数字索引进行索引,也可以通过 普罗米德 所需组件的。确保您的progid实际上是“nlog4vba.logger”(通过 ProgId 属性),并验证该对象是否已使用此ID注册(您可以轻松地在注册表中签入该ID,并搜索分配的GUID)。

        2
  •  0
  •   Duncan Bayne    14 年前

    结果发现我的VBA代码是非常错误的; here 回答是礼貌的吗 Jan Karel Pieterse :

    我想你需要做点什么 这样地:

    Private Sub CommandButton1_Click()
    
            'Declare an object variable using the referenced lib.
            'if all is well, intellisense will tell you what the proper object name is:
            Dim objLogger as NLog4VBA
    
            'Create an instance of the object
            Set objLogger = New NLog4VBA
    
            'Now use the object
            objLogger.Object.Debug "My Context", "My Message"
    End Sub