TOP

VBA-レッスン 9. プロシージャと関数

どのプログラミング言語にも、プロシージャや関数などの概念があります。これらは、Excel の組み込みプログラミング言語 VBA にも含まれていました。

  • 関数は結果を返すルーチンです。関数呼び出しは式であり、他の式または代入ステートメントの右側で使用できます (VBA では「Function」として示されます)。
  • プロシージャは、関数ではないルーチンです。 VBA 内で「Sub」 (「サブルーチン」という単語から) としてマークされます。

  • 手順 (Public - Private)

    この時点で、作成したすべてのプロシージャは Public タイプになっており、どのモジュールからでもアクセスできることを意味します。

     Sub example()
     
     'と同じ:
     Public Sub example()
    

    プロシージャを特定のモジュールでのみ使用できるようにするには、Private キーワードを使用します。

    Private Sub example()
    

    別のプロシージャの途中からプロシージャを実行する

    別のプロシージャ内からプロシージャを実行するには、その名前を入力するだけです。

    これの非常に簡単な例を次に示します。

    Private Sub warning()
        MsgBox "Caution !!!" '"警告!"
    End Sub
    
    Sub macro_test()
        If Range("A1") = "" Then
            warning '=> プロシージャ「warning」を実行
        End If
        '等...
    End Sub
    

    引数

    引数を使用すると、プロシージャの値をサブプロシージャで使用できるようになります (デフォルトでは、変数は宣言されたプロシージャからのみ使用できることに注意してください)。

    Private Sub warning(var_text As String)
        MsgBox "Caution : " & var_text & " !"
    End Sub
    
    Sub macro_test()
        If Range("A1") = "" Then
            warning "empty cell"               '「空のセル」
        ElseIf Not IsNumeric(Range("A1")) Then
            warning "non-numerical value"      '「数値以外の値」
        End If
    End Sub
    

    引数がプロシージャ「warning」に追加されました。この場合、それはタイプ「String」(リボン)の変数「var_text」です。

    Private Sub warning(var_text As String)
    

    このルーチンは引数を取るため、実行するには「warning」の後に値を置く必要があります。

    warning "empty cell"
    

    複数の引数を記述したい場合は、カンマで区切る必要があります。

    オプションの引数

    デフォルトでは、プロシージャに引数がある場合、それらを指定する必要があり、引数が指定されていない場合、プロシージャは実行されません。

    Optional キーワードを使用して、必須の引数の後にオプションの引数を追加できます。例:

    Private Sub dialog_boxes(last_name As String, Optional first_name, Optional age)
    

    このプロシージャは、次のようにオプションの引数の有無にかかわらず実行できるようになりました。

     '例 1: 姓を表示します。
     dialog_boxes last_name1
       
     '例 2: 姓と名を表示します。
     dialog_boxes last_name1, first_name1
       
     '例 3: 姓と年齢を表示します。
     dialog_boxes last_name1, , age1
       
     '例 4: 姓、名、年齢を表示します。
     dialog_boxes last_name1, first_name1, age1
    

    引数は正しい順序で入力する必要があります。

    プロシージャにオプションの引数が存在するかどうかをテストするには、IsMissing 関数を使用します。この関数は、一部の関数タイプ (Variant タイプ) とのみ互換性があり、オプションの引数のタイプが宣言されていない (宣言されていないタイプ = Variant) ため、これは重要です。

    上で説明した 2 つのコード スニペットを使用する例を次に示します。

    Sub macro_test()
    
        Dim last_name1 As String, first_name1 As String, age1 As Integer
       
        last_name1 = Range("A1")
        first_name1 = Range("B1")
        age1 = Range("C1")
    
        '例 1: 姓を表示します。
        dialog_boxes last_name1
       
        '例 2: 姓と名を表示します。
        dialog_boxes last_name1, first_name1
       
        '例 3: 姓と年齢を表示します。
        dialog_boxes last_name1, , age1
       
        '例 4: 姓、名、年齢を表示します。
        dialog_boxes last_name1, first_name1, age1
    
    End Sub
    
    Private Sub dialog_boxes(last_name As String, Optional first_name, Optional age)
       
        If IsMissing(age) Then 'age 変数が欠落している場合...
           
            If IsMissing(first_name) Then '変数 first_name が欠落している場合は、
            							  '姓のみが表示されます
               MsgBox last_name
            Else 'それ以外の場合は、姓と名が表示されます
               MsgBox last_name & " " & first_name
            End If
           
        Else 'age 変数が存在する場合...
    
            If IsMissing(first_name) Then '変数 first_name が欠落している場合は、
                                          '姓と年齢が表示されます
               MsgBox last_name & ", " & age & " years old"
            Else 'それ以外の場合は、姓、名、年齢が表示されます
               MsgBox last_name & " " & first_name & ", " & age & " years old"
            End If
       
        End If
           
    End Sub
    

    見る下の図 (例 1):

    ByRef - ByVal

    デフォルトでは、引数は ByRef 型です。つまり、変数が引数として渡されると、その変数への参照も渡されます。つまり、変数が別のサブプロシージャによって変更された場合、そのサブプロシージャを呼び出す外側のプロシージャでも変数が変更されます。

    例:

    Sub macro_test()
        Dim var_number As Integer
        
        var_number = 30
        calcul_square var_number
       
        MsgBox var_number
    End Sub
    
    Private Sub calcul_square(ByRef var_value As Integer) 'ByRef はオプションです
                                                          '(デフォルト値です)
        var_value = var_value * var_value
    End Sub
    

    明確にするために、マクロの実行が開始された場合に何が起こるかを示す例を以下に示します。

     var_number = 30
     '変数「var_number」の初期値は30です。
    
     calcul_square var_number
     'サブプロシージャは「var_number」を引数として実行されます
    
     Private Sub calcul_square(ByRef var_value As Integer)
     '変数「var_value」は、変数「var_number」に素早くアクセスするためにある程度の役割を果たします。
     'これは、変数「var_value」が変更されると、変数「var_number」も変更されることを意味します。
     '(同じ名前である必要はありません)
     var_value = var_value * var_value
     '変数「var_value」の値が変更されます(したがって、「var_number」も同時に変更されます)
    
     End Sub
     'サブ手順の終了
    
     MsgBox var_number
     '変数「var_number」が変更され、ダイアログに 900 が表示されるようになりました。
    

    2 番目の方法は、ByVal を使用することです。

    参照 (ラベル) を渡す ByRef とは異なり、ByVal は値を渡します。これは、引数として渡された値が変更されていないことを意味します。

    以下に、前のコードと ByVal がどのように機能するかを示します。

     var_number = 30
     '変数「var_number」の初期値は30です。
    
     calcul_square var_number
     'サブプロシージャは「var_number」を引数として実行されます
    
     Private Sub calcul_square(ByVal var_value As Integer)
     '変数「var_value」は変数「var_number」の値をコピーします(2 つの変数は関連しません)
    
     var_value = var_value * var_value
     '変数「var_value」の値が変更されました
    
     End Sub
     'サブプロシージャの終了 (この例では、サブプロシージャは何の影響も与えません)
    
     MsgBox var_number
     '変数「var_number」は変更されていないため、ダイアログ ボックスには 30 が表示されます。
    

    覚えておくべきこと: 変数を変更すべきではない場合は、ByVal を使用します。

    機能

    プロシージャと関数の主な違いは、関数が値を返すことです。

    簡単な例を次に示します。

    Function square(var_number)
        square = var_number ^ 2 '「square」関数は「平方根」値を返します。
    End Function
    
    Sub macro_test()
        Dim result As Double
        result = square(9.876) '結果変数には、関数によって計算された値が割り当てられます。
        MsgBox result '結果が表示されます (この場合は 9.876 の 2 乗)
    End Sub
    

    この関数は、Excel の他の関数と同様にワークシートで使用できます。

    たとえば、セル A1 に入力された値の 2 乗を取得するには、次のようにします。