在任何编程语言中都存在过程和函数等概念。它们还包含在 Excel 的内置编程语言 VBA 中。
此时,我们创建的所有过程都是 Public 类型,这意味着它们可以从任何模块访问。
Sub example() '相同: Public Sub example()
要使该过程仅在某个模块中可用,请使用 Private 关键字:
Private Sub example()
要从另一个过程中执行一个过程,只需输入其名称即可。
这是一个非常简单的例子:
Private Sub warning() MsgBox "Caution !!!" '“警告!” End Sub Sub macro_test() If Range("A1") = "" Then warning '=> 执行程序“warning” End If 'ETC... End Sub
参数使得可以在子过程中使用过程中的值(请记住,默认情况下,变量只能从声明它们的过程中使用)。
Private Sub warning(var_text As String) MsgBox "Caution : " & var_text & " !" End Sub Sub macro_test() If Range("A1") = "" Then warning "empty cell" '“空单元格” ElseIf Not IsNumeric(Range("A1")) Then warning "non-numerical value" '“非数值” End If End Sub
一个参数已添加到过程“warning”中,在本例中,它是“String”类型的变量“var_text”(功能区):
Private Sub warning(var_text As String)
该例程需要一个参数,因此我们需要在“warning”后面放置一个值来执行它:
warning "empty cell"
当我们想写多个参数时,它们应该用逗号分隔。
默认情况下,如果过程有参数,则必须提供它们,如果不提供,则过程将不会被执行。
可以使用Optional 关键字在强制参数之后添加可选参数。例子:
Private Sub dialog_boxes(last_name As String, Optional first_name, Optional age)
现在可以使用或不使用可选参数来执行此过程,如下所示:
'示例1:显示姓氏: dialog_boxes last_name1 '示例 2:我们显示姓氏和名字: dialog_boxes last_name1, first_name1 '示例3:显示姓氏和年龄: dialog_boxes last_name1, , age1 '示例 4:显示姓氏、名字和年龄: dialog_boxes last_name1, first_name1, age1
参数必须按正确的顺序输入。
为了测试过程中是否存在可选参数,我们使用 IsMissing 函数。此函数仅与某些函数类型(类型为 Variant)兼容,这一点至关重要,因为未声明可选参数的类型(未声明类型 = Variant)。
这是使用上面讨论的两个代码片段的示例:
Sub macro_test() Dim last_name1 As String, first_name1 As String, age1 As Integer last_name1 = Range("A1") first_name1 = Range("B1") age1 = Range("C1") '示例1:显示姓氏: dialog_boxes last_name1 '示例 2:我们显示姓氏和名字: dialog_boxes last_name1, first_name1 '示例3:显示姓氏和年龄: dialog_boxes last_name1, , age1 '示例 4:显示姓氏、名字和年龄: dialog_boxes last_name1, first_name1, age1 End Sub Private Sub dialog_boxes(last_name As String, Optional first_name, Optional age) If IsMissing(age) Then '如果年龄变量缺失... If IsMissing(first_name) Then '如果变量first_name丢失,那么 '仅显示姓氏 MsgBox last_name Else '否则,将显示姓氏和名字 MsgBox last_name & " " & first_name End If Else '如果年龄变量存在... If IsMissing(first_name) Then '如果变量first_name丢失,那么 '将显示姓氏和年龄 MsgBox last_name & ", " & age & " years old" Else '否则,将显示姓氏、名字和年龄 MsgBox last_name & " " & first_name & ", " & age & " years old" End If End If End Sub
看下图(例1):
默认情况下,参数的类型为 ByRef,这意味着如果将变量作为参数传递,则也会传递对其的引用。换句话说,如果一个变量已被另一个子过程更改,那么调用该子过程的外部过程也会更改该变量。
例子:
Sub macro_test() Dim var_number As Integer var_number = 30 calcul_square var_number MsgBox var_number End Sub Private Sub calcul_square(ByRef var_value As Integer) 'ByRef 是可选的 '(是默认值) var_value = var_value * var_value End Sub
为了清楚起见,下面是宏开始执行时会发生什么的示例:
var_number = 30 '变量“var_number”的初始值为30 calcul_square var_number '子过程以“var_number”作为参数运行 Private Sub calcul_square(ByRef var_value As Integer) '变量“var_value”在某种程度上用于快速访问变量“var_number”, '这意味着如果变量“var_value”更改,变量“var_number”也会更改 '(而且他们不必有相同的名字) var_value = var_value * var_value '变量“var_value”的值被更改(因此“var_number”也同时更改) End Sub '子程序结束 MsgBox var_number '变量“var_number”已更改,因此对话框中现在将显示 900
第二种方法是使用ByVal。
与传递引用(标签)的 ByRef 不同,ByVal 传递一个值,这意味着作为参数传递的值尚未被修改。
下面您可以看到前面的代码和 ByVal 是如何工作的:
var_number = 30 '变量“var_number”的初始值为30 calcul_square var_number '子过程以“var_number”作为参数运行 Private Sub calcul_square(ByVal var_value As Integer) '变量“var_value”复制变量“var_number”的值(这两个变量不相关) var_value = var_value * var_value '变量“var_value”的值已更改 End Sub '子过程结束(在此示例中,子过程对任何内容都没有影响) MsgBox var_number '变量“var_number”尚未更改,因此对话框中将显示 30
您需要记住的是:当不应更改变量时,请使用 ByVal。
过程和函数之间的主要区别在于函数返回一个值。
这是一个简单的例子:
Function square(var_number) square = var_number ^ 2 '“square”函数返回“平方根”值 End Function Sub macro_test() Dim result As Double result = square(9.876) '结果变量被赋予函数计算的值 MsgBox result '显示结果(在本例中为 9.876 的平方) End Sub
该函数可以像 Excel 中的任何其他函数一样在工作表上使用。
例如,要获取单元格 A1 中输入的值的平方: