用户自定义函数和子程序
在VBA中,执行特定任务的一组命令被放入一个程序中,程序可以是函数或子程序。
函数和子程序之间的主要区别是函数返回结果,而子程序不返回结果。
因此,如果你希望执行有返回结果的任务(例如,一组数字的求和),则通常使用函数,但如果你只需要执行一组操作(例如格式化一组单元格),则可以选择使用子程序。
参数
VBA程序可以通过声明参数来传递数据。例如,使用子程序将整数填充到工作表上当前选定区域中的每个单元格,通过参数将整数值提供给子程序,如下所示:
![30f304d60a0f49bc4a81da93e9941fd7.png](https://i-blog.csdnimg.cn/blog_migrate/19ed570a41696b1370a71c9b939c0e55.jpeg)
请注意,函数或子程序不一定要有参数。有些程序可能不需要它们。
可选参数
也可以为程序定义可选参数。用户可以根据需要提供这些参数,但是如果省略了这些参数,程序将为它们指定一个默认值。
回到上面的例子,如果我们想让所提供的整型参数是可选的,则声明如下:
![1c2e4722816ea67c2001167f8ae4d264.png](https://i-blog.csdnimg.cn/blog_migrate/2d0bdada22075cc575012f0c9da84193.jpeg)
在本例中,整型参数i的默认值为0。
可以在程序中声明多个可选参数,只要这些可选参数都位于参数列表的末尾。
按值和按引用传递参数
参数传递给程序时,可以通过两种方式传递:
- ByVal-参数是通过值传递的。这意味着只将值(即参数的副本)传递给程序,因此,退出程序时,对程序内部参数所做的任何修改不影响到外部。
- ByRef-参数是通过引用传递。这意味着参数的地址被传递给程序。当程序内部发生任何改变时,影响到外部。
在定义程序时,可以使用ByVal或ByRef关键字指定参数是通过值传递还是通过引用传递。如下所示:
![b1bca9c054b87bb5a13e411b2de27ec2.png](https://i-blog.csdnimg.cn/blog_migrate/f835d8415f65cf4a5f5213c3da6c2e9c.jpeg)
在本例中,整数i通过值传递。退出子程序时,对i所做的任何更改都将丢失。
![3a097de43ffc526671ed687807832256.png](https://i-blog.csdnimg.cn/blog_migrate/1c180f1d3313a995080972602f7e8b41.jpeg)
在本例中,整数i是通过引用传递的。退出子程序时,传入子程序的变量将记住对i所做的任何更改。
应该注意的是,默认情况下,参数是通过引用传递的。因此,如果不使用ByVal或ByRef关键字,参数都将按引用传递。
在进一步讨论函数和子程序的性质之前,先单独研究这两种类型的程序。下面两个部分将简要讨论函数和子程序,并提供一些简单的示例。
函数
编辑器可以识别函数,定义函数的语法如下所示:
![2ca8893e91e61e7128071a77c9f56b8f.png](https://i-blog.csdnimg.cn/blog_migrate/bf054702167219bb79c33dabf4c6bc56.jpeg)
如前所述,函数具有返回值,返回值具有以下规则:
- 返回值的数据类型必须在函数签名中声明。
- 返回值必须分配给与函数同名的变量。此变量不需要声明,因为它已经作为函数的一部分存在。
下面的示例对此进行了说明。
函数示例:对3个数字执行数学运算
下面的代码显示了一个简单的函数,该程序接收三个参数,每个参数都是Double类型,它返回一个Double值,即前两个参数的和减去第三个参数的差:
![5fe2e9e12da7b058f90093ff4017a3eb.png](https://i-blog.csdnimg.cn/blog_migrate/47a0b31ad0b29366116795500b848d7b.jpeg)
上面的函数简单地说明了向程序提供参数的方式。还可以看到,函数返回值的类型被定义为Double(在函数签名尾部添加语法as Double)。
上面的示例还显示了函数返回的结果如何存储在与函数同名的变量中。
调用函数
如果在编辑器中将上述函数键入到模块中,则可以从其他VBA程序或从Excel工作表调用该函数。
从VBA代码中调用函数
只需将函数赋给变量,就可以在VBA程序中调用函数,如下所示:
![c85549c440012287bd74e2a1fa81a33f.png](https://i-blog.csdnimg.cn/blog_migrate/ae812f80c7f55263e4e471e716f023e2.jpeg)
从Excel工作表中调用函数
可以从工作表调用函数,操作方法与调用任何内置Excel函数的方法相同。
因此,你可以通过在工作表的任何单元格中键入以下内容来调用SumMinus函数:
![00142f33c69e39085433561d5ef2cff8.png](https://i-blog.csdnimg.cn/blog_migrate/221245b8f44d35d1f67942913dd2ebf3.jpeg)
子程序
编辑器可以识别子程序,定义子程序的语法如下所示:
![a435beda72dd0ee8fc77f0bab26a031e.png](https://i-blog.csdnimg.cn/blog_migrate/e4d1eb40d53a397cb0ed586fdd344800.jpeg)
子程序示例1:居中并将字体大小应用于选定的单元格区域
下面的代码显示了一个简单的子程序,该子程序将格式应用于当前选定的单元格区域。单元格的格式设置为居中对齐(水平和垂直),并具有用户提供的字体大小:
![f7a30675c6f14e12a99106e47faf6408.png](https://i-blog.csdnimg.cn/blog_migrate/a973542666421e0e7700065b372200a2.jpeg)
上面的示例说明了子程序如何执行操作而没有返回值。
此示例还包括可选参数iFontSize。如果未提供参数,则使用默认字体大小10。但是,如果将参数提供给子程序,则当前选择范围将设置为用户提供的字体大小。
子程序示例2:居中并将粗体字体应用于选定的单元格区域
下面的代码与示例1类似,但是没有为选定区域提供字体大小,而是将单元格设置为粗体,此示例显示不接收任何参数的子程序:
![88feb309c466e3026b888f203952db96.png](https://i-blog.csdnimg.cn/blog_migrate/19b54e79d0278df02a10c2579644db2d.jpeg)
调用子程序
从VBA代码中调用子程序
从代码中调用子程序,方法是键入call关键字,然后键入子程序名称,然后键入括号中的子过程参数。如下例所示:
![d85998ede89abf9742a12af2225f0fbc.png](https://i-blog.csdnimg.cn/blog_migrate/4ced81109757d7d04e92c00e71d80978.jpeg)
如果子程序有多个参数,则这些参数将用逗号分隔,例如:
![09370176a9b9d68ff86f725baad53197.png](https://i-blog.csdnimg.cn/blog_migrate/84f47dc46ab7c69897ed43c0815a97be.jpeg)
从Excel工作表中调用子程序
子程序不能像函数那样直接在Excel的工作表中键入,因为子程序不返回值。但是,在子程序不声明参数的情况下(并且是公共的,见下文),用户仍然可以在工作表中使用子程序。因此,上面两个子程序,Format_Centered_And_Bold可以在工作表中使用,Format_Centered_And_Sized则不能(因为它有一个参数)。
对于可从工作簿访问的子程序,运行它们的方法是:
通过以下任一操作打开“宏”对话框:
- 从Excel功能区的“开发人员”选项卡中单击“宏”选项
- 使用键盘快捷键Alt+F8(即在按下Alt键的同时按F8键)
在“宏”对话框中,选择要运行的宏,然后单击“运行”按钮。
为子程序指定快捷键
您可以为子程序指定一个组合键,以使代码能够快速、轻松地执行。为此:
通过以下任一操作打开“宏”对话框:
- 单击Excel功能区“开发人员”选项卡上的“宏”选项
- 使用键盘快捷键Alt+F8(即在按下Alt键的同时按F8键)
在“宏”对话框中,选择要指定组合键的宏;
单击“选项”打开“宏选项”对话框;
在“宏选项”对话框中键入所需的快捷键;
单击“确定”,然后关闭“宏”对话框。
警告:将组合键分配给宏时,请注意不要选择Excel的预定义组合键(如CTRL-C)。如果确实选择了现有的Excel键组合,则宏将覆盖此组合键,并且你或其他用户可能会意外地执行宏代码。
VBA程序的作用范围
在本教程的第2部分中,我们讨论了变量和常量的作用以及Public和Private关键字的作用。这些关键字在应用于VBA程序时具有相同的含义:
![79820494cfb5566277b56ef947b8957d.png](https://i-blog.csdnimg.cn/blog_migrate/0c76bf80e47f7e8135101c8fce792717.jpeg)
如果程序声明前面有关键字Public,则VBA工程中的所有其他模块都可以访问该程序。
![eea79722dcbec4cb8191abb9cf0898ad.png](https://i-blog.csdnimg.cn/blog_migrate/aba93c8ad53ee824d867dee87b6d7554.jpeg)
如果程序声明前面有关键字Private,则该程序仅对当前模块可用,无法从任何其他模块或Excel工作簿中访问它。
如果在函数或子程序的开头没有插入关键字,则默认设置是Public(即可以从VBA工程中的任何位置访问)。这与变量声明不同,变量声明在默认情况下是Private的。
提前退出函数和子程序
如果要在函数或子程序运行到末尾之前退出它,可以使用Exit Function或Exit Function命令执行此操作。如下所示,函数期望接收一个正值来处理,如果接收到的是负值,则函数无法继续,因此它提醒错误后立即退出程序:
![051b5d0d266c962921dda38001d5f9b3.png](https://i-blog.csdnimg.cn/blog_migrate/8175e1635507091e1a7aee5e11b84fb7.jpeg)
在退出VAT_Amount函数之前,上面的代码使用内置的MsgBox函数,向用户显示一个包含警告消息的框。