为Excel工作表函数创建Visual Basic自动化加载项的方法

为Excel工作表函数创建Visual Basic自动化加载项的方法

如何为 Excel 工作表函数创建 Visual Basic 自动化加载项

在 Microsoft Excel 2000 中,不能直接从工作表单元格公式中调用组件对象模型 (COM) 加载项中的函数,而是必须为该 COM 加载项函数创建一个 Visual Basic for Applications (VBA) 包装,以此来间接调用该函数。

在 Excel 2002 和更高版本中,COM 加载项(称为自动化加载项)的集成度已得到增强,现在可以直接从工作表公式中调用 COM 加载项函数而不需要 VBA 包装。本文说明了如何使用 Visual Basic 创建一个自动化加载项,通过该加载项揭示那些能够从 Excel 2002 或更高版本工作表公式中调用的函数。
为Excel工作表函数创建Visual Basic自动化加载项的方法 回到顶端

更多信息

创建自动化加载项示例

1. 在 Visual Basic 中,开始一个新的 AddIn 项目。
2. 默认情况下,该项目中会添加一个名为 frmAddIn 的窗体。为了演示方便,可以从项目中删除该窗体。在项目资源管理器中,右键单击该窗体,然后单击快捷菜单上的“删除 frmAddIn”。
3. 在“项目”菜单上,单击“MyAddin 属性”。将“项目名称”更改为“AutomationAddin”,然后单击“确定”。
4. 在项目资源管理器中,选择“连接设计器”。将其“名称”属性更改为“XLFunctions”。
5. 在项目资源管理器中,双击“XLFunctions”设计器。在“常规”选项卡上,对设计器设置进行如下更改:
从“应用程序”列表中,选择“Microsoft Excel”。
从“应用程序版本”列表中,选择“Microsoft Excel 10.0”。
注意:如果您使用的是 Microsoft Office Excel 2003,请从“应用程序版本”列表中选择“Microsoft Excel 11.0”。
将“初始加载行为”设置更改为“按需加载”。
6. 在 XLFunctions 设计器仍然打开的情况下,从“视图”菜单中选择“代码”。用以下代码替代模块中的代码:
Option Explicit
Private Declare Function GetTickCount Lib "kernel32" () As Long

Dim oApp As Object 'The Excel Application object

Private Sub AddinInstance_OnAddInsUpdate(custom() As Variant)
  Exit Sub
End Sub

Private Sub AddinInstance_OnConnection(ByVal Application As Object, ByVal ConnectMode As AddInDesignerObjects.ext_ConnectMode, ByVal AddInInst As Object, custom() As Variant)
  Set oApp = Application
End Sub

Private Sub AddinInstance_OnDisconnection(ByVal RemoveMode As AddInDesignerObjects.ext_DisconnectMode, custom() As Variant)
  Set oApp = Nothing
End Sub

Private Sub AddinInstance_OnStartupComplete(custom() As Variant)
  Exit Sub
End Sub

Public Function TickCount() As Long
  '----------------------------------------------------------------------
  '** A volatile function that is called each time the sheet is calculated.
  '  Call with =TICKCOUNT().
  '----------------------------------------------------------------------
  oApp.Volatile
  TickCount = GetTickCount
End Function

Public Function Add1(Num1 As Variant, Num2 As Variant) As Variant
  '----------------------------------------------------------------------
  '** A function with two required arguments.
  '  Can be called with formulas such as =Add1(1,3) or =Add1(A1,A2).
  '----------------------------------------------------------------------
  On Error Resume Next
  Add1 = "The sum of " & Num1 & " and " & Num2 & " is " & _
    CDbl(Num1) + CDbl(Num2)
  If Err <> 0 Then Add1 = CVErr(2036) 'xlErrNum = 2036
End Function

Public Function Add2(Num1 As Variant, Num2 As Variant, Optional Num3 As Variant) As Variant
  '----------------------------------------------------------------------
  '** A function with two required arguments and a third optional argument.
  '  Can be called with formulas such as =Add2(1,2), =Add2(A1,A2,A3).
  '----------------------------------------------------------------------
  Dim Sum As Double, sMsg As String
  On Error GoTo Handler
  Sum = CDbl(Num1) + CDbl(Num2)
  If IsMissing(Num3) Then
    sMsg = "The sum of " & Num1 & " and " & Num2 & " is "
  Else
    Sum = Sum + CDbl(Num3)
    sMsg = "The sum of " & Num1 & ", " & Num2 & " and " & Num3 & " is "
  End If
  Add2 = sMsg & Sum
  Exit Function
Handler:
  Add2 = CVErr(2036) 'xlErrNum = 2036
End Function

Public Function Add3(ParamArray Nums()) As Variant
  '----------------------------------------------------------------------
  '** Demonstrates a function with a variable number of arguments.
  '  Can be called with formulas like =Add3(1), =Add3(1,2,3,4),
  '  or =Add3(A1,A2).
  '----------------------------------------------------------------------
  Dim Sum As Double, i As Integer
  On Error GoTo Handler
  For i = 0 To UBound(Nums)
    Sum = Sum + CDbl(Nums(i))
  Next
  Add3 = "The sum is " & Sum
  Exit Function
Handler:
  Add3 = CVErr(2036) 'xlErrNum = 2036
End Function

Public Function ReturnArray(nRows As Long, nCols As Long) As Variant
  '----------------------------------------------------------------------
  '** Demonstrates how to return an array of values (for use in Excel
  '  "array formulas").
  '  Can be called with a formula such as =ReturnArray(1,3).
  '----------------------------------------------------------------------
  On Error GoTo Handler
  ReDim a(0 To nRows, 0 To nCols) As Variant
  Dim r As Long, c As Long
  For r = 0 To nRows - 1
    For c = 0 To nCols - 1
      a(r, c) = "r" & r + 1 & "c" & c + 1
    Next c
  Next r
  ReturnArray = a
  Exit Function
Handler:
  ReturnArray = CVErr(2015) 'xlErrValue = 2015
End Function

Public Function GetArray(Nums As Variant) As Variant
  '----------------------------------------------------------------------
  '** Demonstrates how to use an array(or range of multiple cells) as
  '  a function argument.
  '  Can be called with formulas such as =GetArray(A1:B5), GetArray(A1),
  '  or GetArray({1,2,3;4,5,6}).
  '----------------------------------------------------------------------
  Dim Sum As Double, v As Variant
  On Error GoTo Handler
  If IsArray(Nums) Then
    For Each v In Nums
      Sum = Sum + CDbl(v)
    Next
  Else
    Sum = CDbl(Nums)
  End If
  GetArray = "The sum is " & Sum
  Exit Function
Handler:
  GetArray = CVErr(2036) 'xlErrNum = 2036
End Function

7. 将该加载项构建为 AutomationAddin.dll。

在 Microsoft Excel 2002 或 Microsoft Office Excel 2003 中使用该自动化加载项示例

1. 如果在该 Visual Basic 加载项项目的“应用程序版本”列表中选择的是“Microsoft Excel 10.0”,请启动 Microsoft Excel 2002。
注意:如果在该 Visual Basic 加载项项目的“应用程序版本”列表中选择的是“Microsoft Excel 11.0”,请启动 Microsoft Office Excel 2003。
2. 在“工具”菜单上单击“加载项”,以显示“加载项管理器”对话框。单击“自动化”,在列表中选择“AutomationAddin.XLFunctions”,然后单击“确定”。选择“AutomationAddin.XLFunctions”,然后单击“确定”以关闭“加载项管理器”对话框。
3. 在 A1 单元格中,键入以下公式:
=TickCount()
该公式返回一个大数,该数值代表自系统启动以来所经过的毫秒数。
4. 在新工作簿的单元格 B1 和 B2 中,分别键入数值 2 和 5。
5. 在单元格 B3 中,键入下面的公式:
=Add1(B1, B2)
然后按 Enter。该公式返回“The sum of 2 and 5 is 7”。
6. 在单元格 B4 中,键入下面的公式:
=Add2(B1, B2)
然后按 Enter。该公式返回“The sum of 2 and 5 is 7”。修改公式以使用第三个可选参数:
=Add2(B1, B2, 10)
公式返回“The sum of 2, 5, and 10 is 17”。
7. 在单元格 B5 中,键入下面的公式:
=Add3(1,2,3,4,5,6)
然后按 Enter。公式返回“The sum is 21”。由于 Add3 函数的参数声明为 ParamArray,因此您可以对该函数使用可变数量的参数。

注意:Excel 限定单个工作表函数的参数不得超过 29 个。
8. 在单元格 B6 中,键入下面的公式:
=Add1("x","y")
然后按 Enter。公式返回 #NUM!(xlErrNum),这是因为 CDbl 函数的类型转换无法将字符串“x”和“y”转换为 double 类型。函数遇到运行时错误时的默认返回值为 #VALUE!。如果希望返回不同的错误,请使用错误处理,这样就可以返回任何 Excel 内置错误值(xlErrDiv0xlErrNAxlErrNamexlErrNullxlErrNumxlErrRefxlErrValue)。
9. 选择单元格 E1:G5。键入以下公式:
=ReturnArray(5,3)
然后按 Ctrl+Shift+Enter 将公式输入为数组公式。函数返回唯一值的 5 x 3 数组。
10. 在 I1:J3 单元格输入任意数。在单元格 I4 中,键入下面的公式:
=GetArray(I1:J3)
公式将返回与“The sum is n”类似的结果(此处的 n 是 I1:J3 中的数之和)。在 I5 中,键入下面的公式:
=GetArray({1,2,3,4})
然后按 Enter。公式返回“The sum is 10”。

函数绑定

自动化加载项中的函数绑定位于函数绑定优先级的末尾。如果自动化加载项中的某个函数与 Excel 内置函数同名,则 Excel 内置函数优先。工作簿和常规加载项 (.xla) 中的 VBA 函数也优先于自动化加载项函数。当您自己创建要在 Excel 中使用的函数时,建议函数名称不要与 Excel 内置函数已使用的名称相同。

要明确调用自动化加载项中的函数,可以使用诸如 ServerName.ClassName.FunctionName(...) 的语法在公式中明确指定函数。例如,要调用示例中的 Add1 函数,可以使用下面的语法:
=AutomationAddin.XLFunctions.Add1(1,2)
您只能调用自动化加载项的顶级方法和属性;而不能深入该加载项的对象模型来调用非顶级的函数。

可变函数

可变函数是一种只要工作表上的任意单元格发生更改就重新计算的函数,而不考虑更改的单元格是否与函数有关。Excel 内部的可变函数的一个示例是 RAND() 函数。按 F9 时,可变函数也会重新计算。

要使自动化加载项中的函数可变,请调用 Excel Application 对象的 Volatile 方法。正如以上示例代码所演示的那样,在加载项的 OnConnection 事件期间,可能会检索对 Excel Application 对象的引用。该自动化加载项示例中的 TickCount 函数就是可变函数。请注意,如果对工作表上的任意单元格进行了更改或按了 F9,包含以下公式的单元格:
=TickCount()
将重新计算。

自动化加载项和加载项管理器

在加载项管理器中,自动化加载项的 HKEY_CLASSES_ROOT/<ProgID> 注册表项的默认值用于加载项的名称。请注意,在 Visual Basic 用户界面 (UI) 中没有属性能够设置此项的默认值;然而,可以在注册表编辑器中或在安装加载项期间手动修改此项。

加载项管理器中的自动化加载项的说明始终作为加载项的 ProgID;这一点无法更改。

自动化加载项和函数向导

在 Excel 函数向导中,每个自动化加载项都有它自己的类别。类别名称是加载项的 ProgID;不能为自动化加载项函数指定其他类别名称。此外,在函数向导中无法指定函数说明、参数说明或自动化加载项函数帮助。
为Excel工作表函数创建Visual Basic自动化加载项的方法 回到顶端

参考

有关其他信息,请单击下面的文章编号,查看 Microsoft 知识库中相应的文章:
256624 (http://support.microsoft.com/kb/256624/) 如何将 COM 加载项函数用作 Excel 工作表函数
有关更多信息,请访问下面的 Microsoft 网站:
http://support.microsoft.com/ofd (http://support.microsoft.com/ofd)