VBA 関数に引数を渡す

はじめに

Excel VBA マクロで関数に引数を渡す方法を紹介します。

関数名 (引数名 As 型名) のようにして、引数を持つ関数を作成できます。引数を配列にするには 引数名() As 型名 のようにします。

Sub 関数なら Call 関数名(値) のようにして、引数を渡せます。

Function 関数なら 関数名(値) のようにして、引数を渡せます。

ByVal (値渡し) の引数は、引数の値を変更しても呼び出し元の変数の値は変更されません。

ByRef (参照渡し) の引数は、引数の値を変更すると呼び出し元の変数の値が変更されます。

引数には、複数の値や配列やクラスなどを渡せます。引数を使って処理を分岐させると、柔軟な動作ができます。

関数の作成と呼び出しについては「関数の作成と呼び出し」をご覧ください。
省略可能な引数 (Optional) の呼び出し方は「省略可能な引数と名前付き引数」をご覧ください。
可変長な引数配列 (ParamArray) の呼び出し方は「可変長な引数配列」をご覧ください。
  • 目次
    • 引数を持つ関数を作成する
    • 関数に引数を渡す
    • ByVal (値渡し) と ByRef (参照渡し) の違い
    • 省略可能な引数と可変長な引数

引数を持つ関数を作成する

Sub と Function 関数の両方で同じように引数を作成できます。 引数名 As 型名 のように入力します。

1 つの引数を持つ関数を作成するには次のようにします。

Sub 関数名(引数 As String)

End Sub

Function 関数名(引数 As String) As String

End Function

複数の引数を持つ関数を作成するには、引数を , で区切って複数作成できます。

Sub 関数名(引数1 As String, 引数2 As Integer)

End Sub

引数を配列にするには 引数名() のように () を付けます。配列の長さは渡された配列によって変わります。

Sub 関数名(引数() As Integer)

End Sub

関数に引数を渡す

Sub 関数に引数を渡すには 関数名 値 または Call 関数名(値) のように入力します。

Sub 実行()
    ' 関数に引数を渡す
    サブ "Tips"
    Call サブ("Tips")
End Sub

' この関数に引数が渡される
Sub サブ(引数1 As String)
    Debug.Print(引数1) ' Tips
End Sub

Function 関数に引数を渡すには 関数名(値) のように入力します。

Sub 実行()
    ' 関数に引数を渡す
    Dim s As String
    s = 関数("Tips")
End Sub

' この関数に引数が渡される
Function 関数(引数1 As String) As String
    Debug.Print(引数1) ' Tips
    関数 = 引数1
End Function

どちらの関数でも複数の引数を渡すには 値, 値 … のように , で区切ります。

Sub 実行()
    ' 関数に引数を渡す
    Call サブ ("Tips", 100)
End Sub

' この関数に引数が渡される
Sub サブ(引数1 As String, 引数2 As Integer)
    Debug.Print(引数1) ' Tips
    Debug.Print(引数2) ' 100
End Sub

配列を渡す

引数に渡せる配列は、引数と同じ型の配列だけです。

Sub 実行()
    Dim 動的() As Integer
    Dim 動的不一致 As Long
    Dim 静的(3) As Integer
    Dim 静的不一致(3) As Long
    Call サブ(動的)       ' 渡せる、 引数と同じ型
    Call サブ(動的不一致) ' 渡せない、引数と違う型
    Call サブ(静的)       ' 渡せる、 引数と同じ型
    Call サブ(静的不一致) ' 渡せない、引数と違う型
End Sub

Sub サブ(引数() As Integer) ' 引数の型 Integer の配列だけ受け取れる

End Sub
引数に配列を渡す条件については「配列」の「変数に配列を代入する」をご覧ください。

クラスを渡す

クラスの Instancing プロパティに Private と PublicNotCreatable の設定があります。

1

Sheet1 などのシートに、Public な変数や関数の型に指定できるクラスは PublicNotCreatable に設定されている必要があります。

' Sheet1 のコード
Public 変数 As Class1 ' Public 変数のときは Class1 を PublicNotCreatable にする必要がある

Public Sub サブ(引数 As Class1) ' Public 関数のときは Class1 を PublicNotCreatable にする必要がある

End Sub

Private に設定していると「エラー プライベート オブジェクト モジュールを、パブリック オブジェクト モジュール内で、パブリック プロシージャの引数または戻り値、パブリック データ メンバー、またはパブリックのユーザー定義型のフィールドとして、使用することはできません。」が発生します。

PublicNotCreatable に設定されているクラスの Public 変数や関数についても同様です。

Private に設定されているクラスの中では関係ありません。標準モジュールでも関係ありません。

ByVal (値渡し) と ByRef (参照渡し) の違い

引数には ByVal (値渡し) と ByRef (参照渡し) の 2 種類があります。

ByVal 引数 As 型名 または ByRef 引数 As 型名 のように入力します。省略すると ByRef になります。

Sub 関数名(ByVal 引数val As String, ByRef 引数ref As Integer)

End Sub

引数は値を渡せるだけでなく、変数と同じように引数に値を代入できます。

Sub 関数名(引数 As String)
    引数 = "Tipsfound"
End Sub

この時、ByVal と ByRef で違いがあります。引数に渡した変数の値が関数の呼び出し後に変更されるかどうかです。

  • ByVal:変更されない
  • ByRef:変更される
Sub 実行()
    Dim 変数 As Integer
    変数 = 1

    Call サブVal(変数)
    Debug.Print(変数) ' 1、ByVal だと変更されない

    Call サブRef(変数)
    Debug.Print(変数) ' 2、ByRef だと値が変更される
End Sub

Sub サブVal(ByVal 引数 As Integer)
    引数 = 2 ' ByVal の引数の値を変更する
End Sub

Sub サブRef(ByRef 引数 As Integer)
    引数 = 2 ' ByRef の引数の値を変更する
End Sub

注意点

VBA でやっかいなのは、関数の引数に括弧 () を付けて呼び出すと ByRef でも値が変更されません。

Sub 実行()
    Dim 変数 As Integer
    変数 = 1

    サブRef (変数)
    Debug.Print(変数) ' 1、ByRef でも () があるので変更されない

    サブRef 変数
    Debug.Print(変数) ' 2、ByRef なので値が変更される
    
    変数 = 1
    Call サブRef((変数))
    Debug.Print(変数) ' 1、ByRef でも () があるので変更されない

    Call サブRef(変数)
    Debug.Print(変数) ' 2、ByRef なので値が変更される
End Sub

これは引数に括弧 () を付けると、強制的に ByVal (値渡し) にする仕様のためです。

' ByRef でも変更されない例
Sub 実行()
    Dim 変数 As Integer
    変数 = 1

    ' この括弧は関数を呼び出す括弧ではなく、ByVal にするための括弧です
    サブRef (変数)        

    ' Call の括弧の中に ByVal にするための括弧を付ける
    Call サブRef((変数)) 

    ' Function の括弧の中に ByVal にするための括弧を付ける
    Dim s As String
    s = 関数Ref((変数))   
End Sub

このように間違えて括弧 () をつけるとバグが発生する可能性があります。Sub 関数を呼び出すときは Call を付けるように統一するのをオススメします。

そもそも ByRef はバグの温床になりかねないので使用しないのが一般的です。ただし ByVal を省略すると自動的に ByRef になるので、必ず ByVal を付けるように注意します。ByRef が必要になるときは設計を見直して、引数に ByVal を付けることを心がけます。

省略可能な引数と可変長な引数

ByVal と ByRef 以外に省略可能な引数の Optional と可変長な引数の ParamArray があります。詳しくは次をご覧ください。