更新日:、 作成日:
VBA 関数に引数を渡す
はじめに
Excel VBA マクロで関数に引数を渡す方法を紹介します。
関数名 (引数名 As 型名) のようにして、引数を持つ関数を作成できます。引数を配列にするには 引数名() As 型名 のようにします。
Sub 関数なら Call 関数名(値) のようにして、引数を渡せます。
Function 関数なら 関数名(値) のようにして、引数を渡せます。
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 の設定があります。
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 があります。詳しくは次をご覧ください。
スポンサーリンク