IT系/VBA/基本/プロシージャ(関数)

Last-modified: 2020-08-08 (土) 08:50:52

目次


概要

プロシージャに関するVBAのTIPS。

プロシージャとは

プロシージャは、マクロの最小実行単位。プロシージャは英語で「手続き」や「手順書」の意味。
プロシージャには以下の3種類がある。

  • Functionプロシージャ
  • Subプロシージャ
  • Property プロシージャ

Functionプロシージャ

  • プログラム内で特定の作業を実行し値を返すプロシージャ。
  • Subプロシージャとの違いは、値を返すか返さないかの違い。
  • Functionプロシージャで独自の関数をつくれる(ExcelのセルでSUM関数を使えるように、Functionプロシージャを使うことができる)。
  • Functionステートメントの構文
    [Public | Private | Friend] [Static] Function name [(arglist)] [As type]
    End Function
  • 例文
    ' 戻り値を返す関数
    Function Sum(num1 As Integer, num2 As Integer) As Integer
        Dim total As Integer
        total = num1 + num2
        '戻り値
        Sum = total
    End Sub
    '配列を返す
    Function Test() As Long()
        Dim arr(2) As Long
        arr(0) = 1: arr(1) = 2: arr(2) = 3
        Test = arr()
    End Function
  • Exit FunctionでFunctionを抜けられる。
    Function Proc() As String
        If 条件 Then
            Proc = "exit"
            Exit Function        '条件を満たす場合、Functionプロシージャを抜ける。
        End If
        Proc = "end"
    End Function
  • Java などの return とは異なり、戻り値を設定したあとも処理が続行される。

Subプロシージャ

  • 戻り値を返せない以外は、ファンクションプロシージャと同様。
  • イベントプロシージャは形式上、サブ・プロシージャに属する。
  • 例文
    ' 戻り値を返さない関数
    Sub PrintSum(num1 As Integer, num2 As Integer)
        Dim total As Integer
        total = num1 + num2
        MsgBox total
    End Sub
    '配列を渡す
    Sub Test(arr() As Long)
        Dim val As Variant
        For Each val In arr
            Debug.Print val
        Next
    End Sub
  • Exit SubでSubを抜けられる。
    Sub Proc()
        If 条件 Then
            Exit Sub              '条件を満たす場合、Subプロシージャを抜ける。
        End If
    End Sub

Propertyプロシージャ

  • プロパティを作る際に使用するプロシージャ。以下のような記述になる。
    '扱 う値の型がオブジェクトでない場合
    Private SampleValue_ As Long
    Property Get SampleValue() As Long
        SampleValue  = SampleValue_
    End Property
    Property Let SampleValue(ByVal vData As Long)
        SampleValue_ = vData
    End Property
    '
    ' 扱う値の型がオブジェクトの場合
    Private SampleObject_ As Object
    Property Get SampleObject() As Object
        Set SampleObject  = SampleObject_
    End Property
    Property Set SampleObject(vObject As Object)
        Set SampleObject_ = vObject
    End Property

プロシージャの呼び出し方(Callステートメント)

  • プロシージャの中で他のプロシージャを呼び出すときに、Callステートメントを使う。
    [Call] name [argumentlist]
  • Subプロシージャーに制御を渡す場合のVBA記述方法としては、以下のようにバリエーションがある。
    Sample1
    Call Sample1
    Sample2 arg1, arg2
    Call Sample2(arg1, arg2)
  • Callを省略する場合は、引数リストは括弧で囲わない。
  • Callを記述した場合は、引数リストは括弧で囲う。
  • 下記例のように、あるプロシージャの引数に別のプロシージャの呼び出しを渡す場合などは、丸括弧が必要になる。
    Public Sub OneParameter(a As Integer)
        Debug.Print TwoParameter(a, 10) ' TwoParameter の呼び出しに括弧が必要になる
    End Sub
    Public Function TwoParameter(a As Integer, b As Integer) As Integer
        TwoParameter = a + b
    End Function
  • 変数に代入するときに、右辺でプロシージャを呼ぶ場合も必要になる。
    Public Sub procedure()
        Dim s As String
        s = TypeName("hoge") ' 括弧が必要
        Debug.Print s
    End Sub

プロシージャの引数

Subプロシージャ、Functionプロシージャにおける、引数リストの指定について。

  • 引数は、呼び出し先のプロシージャに渡すデータを指定するもの。以下のarglistの部分のこと。
    Sub name [(arglist)]
    Function name [(arglist)] [As type]
  • arglistは次の形式で指定する。
    [Optional] [ByVal | ByRef] [ParamArray] varname[( )] [As type] [= defaultvalue]

ByValの値渡しとは

変数の中のデータを渡すもので、呼出側の変数は影響を受けない。
つまり、値渡しでは、呼び出し先で引数の値を変更しても、呼び出し元の引数は変更されない。

ByRefの参照渡しとは

変数そのものを渡すもので、呼出側の変数が影響を受ける。
つまり、参照渡しでは、呼び出し先で引数の値を変更すると、呼び出し元の引数も変更される。

  • VBAでは、ByRefがデフォルトである*1
  • ただし、呼び出し元で変数ではなく、関数や数式を引数にした場合や、変数を括弧()で囲んだ場合は値渡し(ByVal)になる。
    以下の記述は、呼び出し先がByRef(参照渡し)てもByVal(値渡し)になる。
    Call 呼び出し先((変数))
    呼び出し先 (変数)
    Call 呼び出し先(関数(変数))
    Call 呼び出し先(変数+変数)

Optionalについて

  • Optional <引数の宣言> = <デフォルト値> とすることで、省略可能な引数を定義できる。
    Public Sub Execute()
        SubProcedure "Explicit Value"
        SubProcedure
    End Sub
    Public Sub SubProcedure(Optional Value As String = "Default Value")
        Debug.Print Value
    End Sub
  • 実行結果
    Explicit Value
    Default Value
  • Optional指定された引数のあるプロシージャを呼び出すときは、Optionalの引数を指定するかしないかを選択できる。
  • Optionalの引数を指定しないと、既定値がある場合はそれが使用される。
  • 既定値が指定されていない場合は、引数は指定された型の初期値が使用される。
  • ただし、Variantの場合はMissingになる。
    省略可能なVariant型の引数がプロシージャに渡されたかどうかを調べるには、IsMissing関数を使用する。

名前付き引数について

引数とは、関数やメソッド等を呼び出すときに渡す値の指定のこと。
この引数を渡す時の記述方法として、名前付き引数がある。

  • 通常、複数の引数がある場合は、その順番通りに指定する。
  • しかし、引数の数が多いと、何番目なのかを意識することは面倒であり混乱しやすい。
  • そこで、引数に名前を付けて、その名前で指定できるようにしたものが、名前付き引数である。
  • 名前付き引数を指定する場合は、「:=」が使われる。この:=は名前付き引数のみで使用される記述になる。
    ' 順番通りの指定
    MsgBox "出来ました。", vbOKOnly, "タイトル"
    ' 名前付き引数を指定
    MsgBox prompt:="出来ました。", Buttons:=vbOKOnly, Title:="タイトル"
  • 名前付き引数は、マクロVBAを読みやすくするためにあるもの。

仮引数と実引数

仮引数とは、関数・メソッド定義時に使用される引数のこと。
実引数とは、その関数・メソッドを実際に使用するときに引き渡す引数のこと。

引数の数を可変にできるパラメーター配列(ParamArray)

  • 引数リストの数を特定せず、不定個数の引数を渡せるよう可変で定義するためには、ParamArrayキーワード(パラメーター配列)を使用する。
  • ParamArrayキーワードは、その引数がバリアント型(Variant)の要素を持つ参照渡し(ByRef)かつ省略可能(Optional)な配列であることを示す。
  • ParamArrayキーワードは、引数リストの最後の引数でしか使用できない。
  • ByVal、ByRef、Optionalの各キーワードと共に使うことはできない。
  • 呼び出し時に、名前付き引数と共に使うことはできない。
  • Option Base ステートメントの影響を受けない。添え字の最小値は必ず0になる。
  • ParamArray引数を省略した場合、IsMissing関数の戻り値はTrueとなり、UBound関数の戻り値は-1となる。
  • ParamArray引数を別のプロシージャに引き渡す場合、引数がByRefで定義されていると以下のコンパイルエラーがでる。
    コンパイルエラー:ParamArrayの使い方が適切ではありません。
    ByValに変えるか、ParamArray引数を一度別のVariant変数に格納してから渡すようにする必要がある。
    Function foo(ParamArray v() As Variant)
        bar1 v     ' これはNG
        bar2 v     ' これはOK
        Dim tmp As Variant : tmp = v
        bar1 tmp   ' ← コピーならOK
        ...
    Sub bar1(ByRef x As Variant)     ' ByRef渡し
    Sub bar2(ByVal x As Variant)     ' ByVal渡し

メソッドとは

  • オブジェクトに対する動作・操作を指定する際のプロシージャのこと。
  • クラスに定義されたFunction、Subをメソッドと呼ぶ(Propertyはプロパティ)。

TIPS

別ページの一覧を入れる。

'IT系/VBA/基本/プロシージャ(関数)/' には、下位層のページがありません。

リンク集

重複を恐れないリンク集。

動画

その他メモ



*1 VB.netではByValのため混乱する。