VBA调用外部函数(工作簿 COM链接库 C链接库)方法

发布于:2019-04-20 | 分类:python/vba/cpp


为便于代码的重复利用和合理组织,VBA支持从当前工作簿调用其他文件中的函数,例如Excel插件*.xlam、宏文件*.xlsm.NET编译和注册的COM链接库*.dll,以及C语言风格的动态链接库*.dll。本文以计算两个单元格数值和为例,简述跨工作簿函数调用方法。

Excel插件/宏文件

可以通过**加载引用**或者**直接调用**两种方式使用Excel插件/宏文件中定义的函数。新建add.xlsm,重命名VBA工程名称为Test_add,然后添加一个模块test_add_module,最后创建如下的add()函数:

' add.xlsm -> test_add_module -> add()
Function add(ByVal A As Object, ByVal B As Object)
    add = A.Value + B.Value
End Function

加载引用

Developer -> Visual Basic -> Tools -> References... -> Browse...,选择add.xlsm文件所在位置,即可将其加载到test.xlsm工程中。test.xlsm工程中出现References节点,包含Reference to add.xlsm子节点。如下图所示,可以通过View -> Object Browser查看是否成功加载add()函数。

接下来即可在VBA代码或者公式编辑器中使用,并且具备智能提示功能。

Debug.Print Add(Range("A1"), Range("B1"))

直接加载

Application.Run()可以跨工作簿使用函数 1

' :param Macro: 被调用函数的绝对地址,格式:workbook.xlsm!module.function
' :Arg1,...Arg30: 最多支持30个位置参数的输入
' :return: 返回Variant类型,可以转换为目标类型
Application.Run (Macro, Arg1, Arg2, ..., Arg30) As Variant

从之前的引用中删除add.xlsm,然后测试如下的调用代码:

Sub test()
    Dim res As Single
    res = Application.Run("'full\path\to\add.xlsm'!test_add_module.add", Range("A1"), Range("B1"))
    Debug.Print res
End Sub

也可以直接在公式编辑器中使用:

=add.xlsm!test_add_module.add(A1,B1)

.NET编译和注册的链接库

类似于调用工作簿中的函数,VBA也可以采用 加载引用直接调用 两种方式引用VB.NET创建的动态链接库类型的COM组件。首先,参考VB.NET封装COM组件 2 的方法创建、编译和注册如下类:

' TestDLL.dll -> Test_add

<ComClass(Test_add.ClassId, Test_add.InterfaceId, Test_add.EventsId)> _
Public Class Test_add

#Region "COM GUIDs"
    ...
#End Region

    ' A creatable COM class must have a Public Sub New() 
    ' with no parameters, otherwise, the class will not be 
    ' registered in the COM registry and cannot be created 
    ' via CreateObject.
    Public Sub New()
        MyBase.New()
    End Sub

    Function add(ByVal A As Object, ByVal B As Object)
        Return A.Value + B.Value
    End Function

End Class

加载引用

同上在Tools -> References加载注册后的文件TestDLL.tlb,然后测试如下调用代码,同理具备智能提示功能。

Sub test()
    Dim OBJ As Test_add
    Set OBJ = New Test_add
    Debug.Print OBJ.Add([A1], [B1])
End Sub

我们也可以通过程序的方式自动加载引用,ThisWorkbook.VBProject.References,具体参考VBA自动添加前期引用的文章 3

直接调用

如果不想前期显式地引用库文件,可以使用CreateObject("COM_DLL_name.class_name")创建已注册的类,然后使用其中的函数。参考代码:

Sub test()
    Dim OBJ As Object
    Set OBJ = CreateObject("TestDLL.Test_add")
    Debug.Print OBJ.Add([A1], [B1])
End Sub

C风格动态链接库

VBA可以采用如下方式引用C语言风格的动态链接库函数:

' 64 bit dll
Private Declare PtrSafe Function [function_name] Lib ["path_to_dll"] ([parameters_list]) As [type]
' 32 bit dll
Private Declare Function [function_name] Lib ["path_to_dll"] ([parameters_list]) As [type]

具体细节和注意事项参考此前的文章VBA调用c++动态链接库