【VBA基礎②】プロシージャについて
皆さんはVBAのプロシージャの仕組みについて知っていますか?プロシージャは、一連の処理をまとめたブロックで、特定の機能を実行するコードの単位(マクロ)です。今回はSubプロシージャやFunctionプロシージャについて詳しく解説したので、この記事を読めばプロシージャについての理解を深めることができますよ!
この記事はVBAの基礎シリーズです。他の記事は以下のリンクからご覧いただけます!
プロシージャとは
プロシージャとはひとつのコードのまとまりです。別の言い方をすれば、「マクロの最小実行単位」です。なので、プロシージャを1個作成すると、そのプロシージャは1つのマクロとして登録されます。
適当にプロシージャを作成し、Excelの「開発」タブより「マクロ」をクリックすると、作成したプロシージャがマクロとして登録されています。

1つのプロシージャは以下のように「Sub マクロ名」で始まり「End Sub」で終わります。これをSubプロシージャと呼びます。
Sub マクロの名前()
処理
End Sub
VBAはSubプロシージャの他にもFunctionプロシージャなどがあります。
Functionプロシージャ
「Function マクロ名」で始まり「End Function」で終わるプロシージャをFunctionプロシージャと呼びます。Functionプロシージャは数学の関数のようなもので、引数を受け取ってその結果を呼び出し元に返すことができます。実際にFunctionプロシージャを作成し、その動作を確認してみましょう。
以下のように各地域と時間帯による外気温をまとめたデータを用意してみました。このデータから地域と時刻を引数に指定したとき、外気温を取り出す関数をFunctionプロシージャで作成してみます。

Functionプロシージャの書式は次のような書き方です。
Function プロシージャ名(引数 As 引数の型)As 変数の型
()内の引数の型はFunctionプロシージャに指定した引数の変数型です。()の後ろに記述する変数の型はFunctionプロシージャの実行結果に対する変数型です。今回は引数として「地域」と「時刻」を使用し、引数に文字列を入れる必要があるので、変数型はStringとします。実行結果としては外気温の「数字」を返すので、実行結果に対する型はDoubleとしておきます。つまり今回のFunctionプロシージャはこうなります。

「String」は文字列の型、「Double」は実数の型です。
変数宣言については前回の記事にまとめています。
Function temp(place As String , time As String) As Double
処理
End Function
プロシージャ名や引数に使用する文字は意味にあるものにしておくと、後ほど見直した時にコードが見やすくなります。
次はどのように目的の外気温を取得するかを考えてみます。今回は目的の外気温は地域と時刻によって決まりますから、地域の行番号と時刻の列番号が分かれば外気温のセルの値を取得できそうです。
この場合はIfステートメントとFor Nextステートメントを組み合わせでコードが組めそうです。

IfステートメントとFor Nextステートメントについても、前回の記事でまとめています。
まず、変数として「x , y , i」の3つを宣言しておきます。これらは整数型としておきます。
Dim x As Integer, y As Integer, i As Integer
次に地域の行を特定するコードを書きます。地域の行は3から13まであるので、Forによる繰り返しは「i」の値3から13まで1ずつ増加するようにします。地域は引数「place」に代入したので、この値と i 行1列目のセルが一致したときxに行番号を代入するようにします。「Exit For」はForループから抜け出す命令文ですので、条件が一致したらループから抜け出せるようにIf文の処理の中に記載しておきます。
For i = 3 To 13
If Cells(i, 1) = place Then
x = i
Exit For
End If
Next i
次に時刻を特定するコードを書きます。考え方は地域を特定する時と同じです。時刻の引数は「time」としたので、対象の時刻と一致したときに列番号を変数に代入します。
For i = 2 To 5
If Cells(2, i) = time Then
y = i
Exit For
End If
Next i
変数 x と y に外気温セルの行と列番号が代入されたので、これを実行結果としてまとめます。これで「temp」に外気温のセル番号が入りました。
temp = Cells(x, y)
Functionプロシージャは完成したので、これを呼び出すためにSubプロシージャを作成します。外気温を取得したいセル番号にさきほど作成したFunction関数を代入するコードを書きます。tempの()内が引数「place」と「time」にあたるので、(place , time)の順で場所と時刻を入れるセル番号を代入します。
Sub 外気温呼び出し()
Cells(5, 9) = temp(Cells(5, 7), Cells(5, 8))
End Sub
以上のコードをまとめます。これでSubプロシージャを実行するとFunctionプロシージャの結果がSubに返され、Function関数の結果がセルの入力されます。

地域と時刻を選び、これを実行すると外気温の値が入力されました。


セルに直接Function関数を入力し、引数を指定しても同様の結果を得られます。

以上のように計算結果を返す関数のプロシージャはFunction、呼び出しされても結果を返さないプロシージャはSubで作成します。Subプロシージャの呼び出しは次に紹介します。
プロシージャの呼び出し
モジュール内の任意のプロシージャから他のプロシージャを呼び出すときは「Call」ステートメントを使用します。次のマクロは「計算を呼び出し」プロシージャを実行すると「計算」プロシージャが呼び出され、セルB1に計算結果の「150」が入力されます。
Sub 計算呼び出し()
Cells(1, 1) = 100
Call 計算
End Sub
Sub 計算()
Cells(1, 2) = Cells(1, 1) + 50
End Sub

「Call」ステートメントは省略することが可能です。
プロシージャの引数
引数の指定
Functionプロシージャでも説明したように、Subプロシージャについても引数として別のプロシージャへデータを渡すことができます。
「test2」プロシージャには引数としてstrを宣言しておきます。「test1」から「test2」を呼び出す際に引数として「こんにちは」と入れてみます。これを実行すると「test2」メッセージは「こんにちは」と表示され、「test1」から引数がデータとして渡されたことが分かります。
Sub test1()
Call test2("こんにちは")
End Sub
Sub test2(str As String)
MsgBox str
End Sub


「MsgBox」は指定した変数や文字を表示する命令文です。
参照渡しと値渡し
引数の渡し方には「参照渡し」と「値渡し」があります。参照渡しは変数そのものを渡します。次のコードは参照渡しで別プロシージャを呼び出しするコードです。
これを実行すると結果は「Hello」となり、「参照渡し先」の処理結果が反映されたことが分かります。
Sub 参照渡し()
Dim str As String
str = "こんにちは"
Call 参照渡し先(str)
MsgBox str
End Sub
Sub 参照渡し先(msg As String)
msg = "Hello"
End Sub
次に値渡しで引数を渡すコードを書いてみます。値渡しは変数の値のみを渡します。
これを実行すると結果は「こんにちは」となり、「値渡し先」の処理結果は反映されていません。
Sub 値渡し()
Dim str As String
str = "こんにちは"
Call 値渡し先(str)
MsgBox str
End Sub
Sub 値渡し先(ByVal msg As String)
msg = "Hello"
End Sub
これは引数の定義に「ByVal」というワードを付け足したからです。「ByVal」はプロシージャの引数を定義する際に「値渡し」を定義するものです。反対に参照渡しを定義する際は「ByRef」を付け足します。記載を省略した場合はすべて「ByRef」で渡したものとして認識されます。
引数の省略
プロシージャで引数を定義するときに、引数の入力が省略された場合の処理を設定することができます。
先ほどの外気温を取得するFunctionプロシージャの引数「time」の前に「Optional」と入れます。これは省略可能な引数を定義する時に使用します。引数が省略された場合の処理として、初期値を割り振っておく必要があるので、引数部分に「="9時"」と入力しておきます。これで、時刻の入力が省略された場合は「time」に「9時」が入力されて処理されます。
Sub 外気温呼び出し()
Cells(5, 9) = temp(Cells(5, 7))
End Sub
Function temp(place As String, Optional time As String = "9時") As Double
Dim x As Integer, y As Integer, i As Integer
For i = 3 To 13
If Cells(i, 1) = place Then
x = i
Exit For
End If
Next i
For i = 2 To 5
If Cells(2, i) = time Then
y = i
Exit For
End If
Next i
temp = Cells(x, y)
End Function
これを実行すると時刻には9時が入るので、札幌の9時の外気温が取得されます。

まとめ
いかがでしたでしょうか?今回はVBAのプロシージャについてまとめました。この記事はVBAの基礎シリーズとして今後も発信していきますので、良ければ他の記事も読んでいただければ嬉しいです。それで最後までお読みいただき、ありがとうございました。