サイトについて      連絡先   検索

VBA 関数に引数を渡す

はじめに

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

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

複数の値や配列やオブジェクトを渡せます。引数を使って処理を分岐させるなど、柔軟な動作ができます。

  • 目次
    • 引数を持つ関数を作成する
    • 関数に引数を渡す
    • ByVal と ByRef の違い
    • 省略可能な引数と可変長な引数

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

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

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


Function 関数名(引数 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

オブジェクトを渡す

オブジェクトとはクラスで作成されたものです。Sheet1 などのワークシートもオブジェクトです。

オブジェクトの Instancing プロパティに Private と PublicNotCreatable の設定があります。

1

PublicNotCreatable のクラスで宣言されている Public な変数や関数などの型には PublicNotCreatable のクラスだけを指定できます。

Sheet1 などは PublicNotCreatable になっています。クラスモジュールの既定値は Private です。そのため自作したクラスを Sheet1 から Public で使用するには PublicNotCreatable にする必要があります。


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

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

End Sub

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

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 で違いがあります。引数に渡した変数の値が関数呼び出し後に変更されるかどうかです。


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 なので値が変更される
    
    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 があります。詳しくは次をご覧ください。

  • 目次
    • 引数を持つ関数を作成する
    • 関数に引数を渡す
    • ByVal と ByRef の違い
    • 省略可能な引数と可変長な引数