概要
對於一般的 VBA 程序來說, 可能一個或幾個函數就行了. 畢竟, VBA 只是作為 excel 的輔助工具來用的.
但是, 隨着 VBA 寫的越來越多, 用個工程來管理就有必要了, 而一個代碼工程的基礎, 就是 函數 和 模塊.
函數
VBA 的中的函數有 2 種, 一種是 Sub, 一種是 Function 在 VBA 中, 其實 Sub 叫過程, 不叫函數, 它們的區別有 2 個:
- Function 有返回值, Sub 沒有
- Sub 可以直接執行, Function 必須被調用才能執行
Sub 和 Function 的示例如下:
1 Option Explicit
2
3 Sub CallAnotherMod()
4 Dim sum As Integer
5 sum = Add(2, 3)
6 Debug.Print sum
7 End Sub
8
9 Function Add(a As Integer, b As Integer) As Integer
10 Debug.Print a
11 Debug.Print b
12 Add = a + b
13 End Function
注意, 函數的返回值, 是將結果賦值給函數名本身 Add = a + b , 否則返回值一直是 0
模塊
模塊化的目的是復用, 對於一些通用的功能, 我們可以封裝成模塊並導出. 這樣, 在不同的 VBA 工程中導入已有的模塊, 就不用重復的造輪子.
模塊的導出很方便, 只要在對應的模塊上點擊右鍵, 導出即可, 導出后是一個 *.bas 的文件.
一般模塊
一般模塊簡單明了, 我們之前寫的 Sub 或者 Function 其實都在一個默認的一般模塊中. 下面的示例工程, 我創建 2 個模塊, 分別是 Main 和 MyMath, Main 用來測試, MyMath 中是為了以后復用的函數.
-
Main 模塊:
1 Option Explicit 2 3 Sub CallAnotherMod() 4 Debug.Print "2 + 3 = " & (Add(2, 3)) 5 Debug.Print "2 * 3 = " & (Multiply(2, 3)) 6 7 End Sub
-
MyMath 模塊:
1 Option Explicit 2 3 Function Add(A As Integer, B As Integer) As Integer 4 Add = A + B 5 End Function 6 7 Function Multiply(A As Integer, B As Integer) As Integer 8 Multiply = A * B 9 End Function
-
運行 Main 模塊, 結果如下:
2 + 3 = 5 2 * 3 = 6
類模塊
除了像上面那樣通過函數來封裝一些功能, VBA 也可以按照類的方式來組織, 熟悉面向對象設計的開發人員可能更喜歡這種方式.
-
新建一個類模塊, 和新建普通模塊的步驟一樣, 只是新建之前選擇的類型是 類模塊
-
比如我們新建一個 MathCls 的類模塊:
1 Option Explicit 2 3 ' 常量, class說明 4 Const MathClsName = "math class" 5 6 Dim MathA As Integer 7 Dim MathB As Integer 8 9 ' 相當於其他面向對象語言中的 set 方法 10 Public Property Let A(numA As Integer) 11 MathA = numA 12 End Property 13 14 ' 相當於其他面向對象語言中的 get 方法 15 Public Property Get A() As Integer 16 A = MathA 17 End Property 18 19 ' 相當於其他面向對象語言中的 set 方法 20 Public Property Let B(numB As Integer) 21 MathB = numB 22 End Property 23 24 ' 相當於其他面向對象語言中的 get 方法 25 Public Property Get B() As Integer 26 B = MathB 27 End Property 28 29 Function Add() As Integer 30 Add = MathA + MathB 31 End Function
-
用來測試的 Main 模塊, 這是個普通模塊
1 Option Explicit 2 3 Sub CallAnotherMod() 4 5 Dim mc As New MathCls 6 mc.A = 2 7 mc.B = 3 8 9 Debug.Print (mc.Add()) 10 11 End Sub
總結
無論采用那種方式來封裝, 要看需要封裝的功能適合那種方式. 這 2 種方式就像函數式和面向對象編程一樣, 沒有誰高誰低, 各自有適合的場景.