【问题标题】:How can I launch an Access add-in (not COM add-in) from VBA code?如何从 VBA 代码启动 Access 加载项(不是 COM 加载项)?
【发布时间】:2020-07-01 03:23:05
【问题描述】:

在 Microsoft Access 中,我有一个加载项 (*.accda) 函数,我想 从 VBA 调用 就像我从 Database Tools -> Add 中单击项目一样-ins 菜单。

在注册表中,有一个列出库路径和表达式的键,但是我还没有找到一个地方可以将调用它的能力暴露给 VBA。

我最接近的是添加对库的引用,然后立即删除该引用。这会加载 VBE 项目并允许我调用该函数而无需添加对项目的持久引用。

With References
    .AddFromFile Environ$("AppData") & "\Microsoft\AddIns\Version Control.accda"
    .Remove references("MSAccessVCS")
End With
Run "MSAccessVCS.AddInMenuItemLaunch"

问题是如果我关闭CurrentDB,则不再加载该库。另一方面,如果我通过加载项菜单调用加载项,它即使在当前数据库关闭时也保持不变。

由于插件需要执行包括关闭当前数据库的功能,所以只有在我通过菜单启动插件时才有效。

是否有人找到system commandWizHook 引用、API 调用或其他可以像单击加载项菜单中的链接一样启动加载项的函数?这里的最终目标是创建一个自动化的 DevOps 流程,在该流程中数据库打开并调用插件功能,无需任何用户干预(即菜单点击)。

工作解决方案

非常感谢 Victor K 在正确的方向上 pointing me!事实证明,您实际上可以在Application.Run 函数中包含一个文件路径,以在应用程序级别加载一个加载项,这是从菜单命令启动加载项时发生的情况。

语法类似于您在 Microsoft Excel 中加载加载项的方式,但到目前为止,我还没有想出如何成功地将过程名称添加到文件路径中以在单个中调用加载项函数称呼。相反,我采用两步方法,第一个调用加载库,第二个调用运行我的加载项函数。我已在我的 VBA 代码中将其作为函数实现。

希望没有人在他们的加载项函数中实际使用 30 个命名参数,:-) 但我继续在第二个示例中添加了所有这些参数,以完全反映 Application.Run 的功能。

' Example of calling an add-in function.
Public Sub ShowVersionControl()
    RunAddin Environ$("AppData") & "\Microsoft\AddIns\Version Control.accda", "MSAccessVCS.AddInMenuItemLaunch"
End Sub


' Simple function to demonstrate concept:
Public Sub RunAddin(strPath As String, strFunction As String)
    ' The following lines will load the add-in at the application level,
    ' but will not actually call the function. Ignore the error of function not found.
    On Error Resume Next
    Application.Run strPath & "!DummyFunction"
    Application.Run strFunction
End Sub


' More robust function with full parameter support for .Run()
Public Sub RunAddin2(strPath As String, strFunction As String, _
    Optional Arg1, Optional Arg2, Optional Arg3, Optional Arg4, Optional Arg5, _
    Optional Arg6, Optional Arg7, Optional Arg8, Optional Arg9, Optional Arg10, _
    Optional Arg11, Optional Arg12, Optional Arg13, Optional Arg14, Optional Arg15, _
    Optional Arg16, Optional Arg17, Optional Arg18, Optional Arg19, Optional Arg20, _
    Optional Arg21, Optional Arg22, Optional Arg23, Optional Arg24, Optional Arg25, _
    Optional Arg26, Optional Arg27, Optional Arg28, Optional Arg29, Optional Arg30)
    
    Dim lngError As Long
    
    ' Trap and ignore expected error.
    On Error Resume Next
    
    ' The following lines will load the add-in at the application level,
    ' but will not actually call the function. Ignore the error of function not found.
    Application.Run strPath & "!DummyFunction"
    
    ' Check returned error just in case it was something else.
    lngError = Err.Number
    If Err Then Err.Clear
    On Error GoTo 0
    If lngError <> 2517 Then Err.Raise lngError
    
    ' Now that the library is loaded, we can call the function.
    Application.Run strFunction, _
        Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9, Arg10, _
        Arg11, Arg12, Arg13, Arg14, Arg15, Arg16, Arg17, Arg18, Arg19, Arg20, _
        Arg21, Arg22, Arg23, Arg24, Arg25, Arg26, Arg27, Arg28, Arg29, Arg30

End Sub

现在我可以成功调用插件中的函数,使其在应用程序级别加载。这允许加载项关闭当前数据库并在完全自动化的过程中从源代码重建它。

注意:使用此方法时,您可能需要添加受信任的位置以允许加载项在没有安全警告的情况下运行。

【问题讨论】:

  • 使用Application.Run 调用该加载项中的空函数来加载它是否有效?另外,为什么将此加载项永久添加到引用中不起作用?
  • @VictorK - 根据我的测试,在加载库之前调用该函数不起作用。我宁愿不将其添加为永久参考,因为它是由开发人员严格使用的,而不是最终用户。 (有关插件here的更多详细信息。)
  • 我使用Application.Run "'X:\Filepath\MyAddIn.xlam'!Ping" 为某些用户预加载加载项,其中PingMyAddIn 中的一个空子。这会加载MyAddIn。它没有为 Access 测试它,所以它可能根本不适合它。对于未通过引用加载的文件,也可能存在一些安全限制。也许我也误解了您想要实现的目标。
  • @VictorK - 不错!!我不知道您可以将完整的文件路径传递给 Application.Run 函数。我们真的很亲近!它加载加载项文件,但我认为 Microsoft Access 中指定函数名称的部分的语法可能不同...
  • 加载插件后你运行的是什么类型的函数?加载插件后有什么问题?

标签: vba ms-access


【解决方案1】:

要加载包含宏的加载项或文件,您可以使用 Application.Run 和文件的完整路径,如下所示:

在插件中创建一个空的子程序,例如:

Public Sub Ping()
End Sub

从需要加载插件的项目中调用这个子程序:

Application.Run "'X:\ExamplePath\Addins\MyAddIn.accda'!Ping"

事实上,您通常可以使用它来立即调用您想要的任何子程序:

Application.Run "'X:\ExamplePath\AddIns\MyAddIn.accda'!SubIWnatToRunInTheAddIn"

您也可以以与后期绑定类似的方式使用此方法(另外您也可以传递参数):

在插件中:

Public Function NewAddInClass() as AddInClass
Set NewAddInClass = New AddInClass
End Function

在调用代码中:

Public Sub CallAddInClass()
Dim TestClass as Object
Set TestClass = Applcation.Run ("'X:\AddinPath\MyAddIn.accda'!NewAddInClass")
TestClass.ExampleMethod
End Sub

我不经常使用 Access,但似乎 Access 具有 CurrentProject 对象,您也许可以通过类似的方式从加载项返回对它的引用,这样您就可以访问 AllMacrosAllModules

【讨论】:

  • 谢谢,维克多!这里的关键是使用Application.Run 中的完整路径。这会在 应用程序级别 加载加载项,这正是我想要实现的。我将编辑我的问题以包含使用这种方法的工作示例。
【解决方案2】:

为什么不只记录一个在应用打开时运行的手动加载宏,并在关闭应用时运行另一个卸载它的宏?

【讨论】:

  • 嗯,您可能想详细说明如何做到这一点。 Access 没有宏记录器。
猜你喜欢
  • 2011-04-08
  • 2017-03-10
  • 2018-09-18
  • 1970-01-01
  • 1970-01-01
  • 2017-05-18
  • 1970-01-01
  • 2019-11-26
  • 2010-12-06
相关资源
最近更新 更多