Functionプロシージャって使ってますか? Excelにはたくさんの関数が用意されていますが、これらの関数と同じように自分で計算式などを作って処理を行いたい場合にFunctionプロシージャを使います。
この記事では、Functionプロシージャについて
- Functionプロシージャとは
- Functionの定義
- Functionを呼び出す方法
- 引数の指定について
という基本的な内容から、
- 戻り値にオブジェクトを指定する方法
- 引数、戻り値に配列を指定する方法
など応用的な内容についてもわかりやすく解説していきます。
Functionプロシージャとは
FunctionプロシージャはVBAの関数のように自分で処理内容を定義して関数を作ることができます。関数とは処理のひとかたまりのことです。変数や配列などの値を使って処理を行います。また、指定して処理結果を取得することもできます。
処理に使う変数や配列などを引数といいます。関数内では引数もしくは関数内で定義した変数、オブジェクトのみを使用することができます。
また返す処理結果のことを戻り値といいます。戻り値には変数やオブジェクトなど1つ指定することができます。
他にも処理内容を定義できるプロシージャとして、Subプロシージャがあります。
Subプロシージャは戻り値を指定できないのに対して、Functionプロシージャは戻り値を指定する点が大きな違いのひとつです。
Functionの定義
まずはFunctionプロシージャを定義する方法についてみていきましょう。Functionプロシージャが戻り値を返さない場合と返す場合とに分けて解説します。ここでは引数なしの場合について解説し、引数ありの場合は後ほど解説します。
引数なし、戻り値なしの定義について
まずは戻り値なしの基本的な定義の記述からみていきましょう。
Function プロシージャ名() 処理の内容 End Function
記述例は以下のようになります。
Function func1() MsgBox "Hello VBA!" End Function
この例では、Functionプロシージャfunc1を定義しています。func1の戻り値はなしで、MsgBox関数を実行します。
引数なし、戻り値ありの定義について
戻り値がある場合の定義の記述は以下のとおりです。
Function プロシージャ名() As 戻り値のデータ型 プロシージャ名 = 戻り値 End Function
変数の定義のようにプロシージャ名と戻り値のデータ型を記述します。プロシージャ名には処理の結果得られる戻り値を代入します。
記述例は以下のようになります。
Function func1() As String func1 = "Hello VBA!" End Function
この例では、Functionプロシージャfunc1を定義しています。func1の戻り値のデータ型はString型で、戻り値は”Hello VBA!”となります。
Functionを呼び出す方法
Functionプロシージャを使うために、呼び出す方法について解説していきます。Functionプロシージャの呼び出し方は戻り値なしの場合と、戻り値ありの場合で異なります。
戻り値なしの場合はCallステートメントを使って呼び出します。Callステートメントは他のSubプロシージャやFunctionプロシージャなどを呼び出す場合に使います。
それぞれの場合についてみていきましょう。
Callで呼び出す方法
戻り値なしのFunctionプロシージャを呼び出す場合は、Callステートメントを使います。
以下のように記述します。
Call Functionプロシージャ名
サンプルコードで確認しましょう。
Sub macro1() Call func1 End Sub Function func1() As String MsgBox "Hello VBA!" End Function
実行結果:
このサンプルコードでは、戻り値なしでMsgBox関数を実行するFunctionプロシージャfunc1を定義しています。これをCallステートメントを使って呼び出しています。
Callステートメントは省略することもできます。呼び出すFunctionプロシージャに引数を渡すとき、Callステートメントを省略しない場合は、引数を「( )」(括弧)で囲みます。
引数のない場合、Callステートメントを省略する場合は、引数を「( )」(括弧)で囲みません。
戻り値ありを呼び出す方法
戻り値ありのFunctionプロシージャを呼び出す際には下記のように記述します。
Dim オブジェクト名 As 戻り値のデータ型 オブジェクト名 = プロシージャ名
まず、Functionプロシージャの戻り値を代入するオブジェクトを用意します。用意したオブジェクトに呼び出すFunctionプロシージャ名を指定して代入します。
それではサンプルコードで確認しましょう。
Sub macro1() Dim str As String str = func1() MsgBox str, vbInformation End Sub Function func1() As String func1 = "Hello VBA!" End Function
実行結果:
このサンプルコードでは、戻り値のデータ型がString型で戻り値が”Hello VBA!”のFunctionプロシージャfunc1を定義しています。
また、Subプロシージャmacro1ではfunc1を呼び出すためにString型のオブジェクトstrを用意し、strにfunc1を代入しています。これをMsgBoxを使って出力表示しています。
引数の指定について
これまでは引数のない基本的な定義について解説してきました。Functionプロシージャを使って処理をする場合、引数に指定した変数を使って戻り値の処理を行う場合がほとんどです。
引数を指定する方法についてみていきましょう!
引数が一つの場合
引数が1つの場合からみていきましょう。引数が1つの場合は以下のように記述します。
Function プロシージャ名(ByVal 引数名 As データ型) As 戻り値のデータ型 プロシージャ名 = 戻り値 End Function
引数が1つの場合はプロシージャ名の後の「()」の中にByVal句を使って引数名とそのデータ型を指定します。
なお、ByVal句の他にByRef句を使う場合があります。ByVal句とByRef句の使い分けについては後ほど解説します。
それでは実際の使い方をサンプルコードで確認しましょう。
Sub macro2() Dim str As String Dim num As Integer num = 3 str = func2(num) MsgBox str, vbInformation End Sub Function func2(ByVal num As Integer) As String Dim square As Integer square = num ^ 2 func2 = CStr(num) & " ^ 2 = " & CStr(square) End Function
実行結果:
このサンプルコードでは、Integer型の引数を1つ持つFunctionプロシージャfunc2を定義しています。
func2ではInteger型の引数numを使って二乗の計算をしています。その結果を用いて文字列を作り、戻り値としています。ちなみにCstr関数は引数に指定した値を文字列型(String)に変換します。
func2はInteger型の変数numを指定して呼び出しています。
引数が複数の場合
引数が2つ以上の複数の場合は以下のように記述します。
Function プロシージャ名(ByVal 引数名1 As データ型, ByVal 引数名2 As データ型, ・・・) As 戻り値のデータ型 プロシージャ名 = 戻り値 End Function
このように「,」(カンマ)で区切って並べます。
それではサンプルコードで確認しましょう。
Sub macro3() Dim str As String str = func3(2, 3) MsgBox str, vbInformation End Sub Function func3(ByVal num1 As Integer, ByVal num2 As Integer) As String Dim mul As Integer mul = num1 * num2 func3 = CStr(num1) & " * " & CStr(num2) & " = " & CStr(mul) End Function
実行結果:
このサンプルコードでは、Integer型の引数を2つ持つFunctionプロシージャfunc3を定義しています。func3ではInteger型の引数num1、num2を使ってかけ算の計算をしています。
その結果を用いて文字列を作り、戻り値としています。func3はInteger型の値2と3を指定して呼び出しています。
参照による引数渡しについて
先ほど引数を指定する際にByVal句を使用する場合とByRef句を使用する場合があるとお伝えしました。
ByVal句は引数をFunctionプロシージャ内に値を渡すためだけの場合に使用します。これに対してByRef句を使うと、Functionプロシージャ内に値を渡すためだけではなく、その値が変更されても変更後の値を取得することができます。
ByVal句を使った引数渡しを値渡しといいます。ByRef句を使った引数渡しを参照渡しといいます。
「ByRef」句を使う場合の記述は下記のようにByVal句をByRef句に替えるだけです。
Function プロシージャ名(ByRef 引数名 As データ型) As 戻り値のデータ型 プロシージャ名 = 戻り値 End Function
また「ByVal」句や「ByRef」句は記述を省略することができます。省略した場合は「ByRef」句を記述した場合と同じく参照渡しとみなされます。
参照渡しで値を変更されたくない場合は注意しましょう!
それでは実際にサンプルコードで確認します。
Sub macro4() Dim sum As Integer Dim mul As Integer Dim num1 As Integer Dim num2 As Integer num1 = 2 num2 = 3 sum = 0 mul = func4(num1, num2, sum) Dim str As String str = CStr(num1) & " + " & CStr(num2) & " = " & CStr(sum) & ", " & CStr(num1) & " * " & CStr(num2) & " = " & CStr(mul) MsgBox str, vbInformation End Sub Function func4(ByVal num1 As Integer, ByVal num2 As Integer, ByRef sum As Integer) As Integer sum = num1 + num2 func4 = num1 * num2 End Function
実行結果:
このサンプルコードではFunctionプロシージャfunc4で足し算とかけ算の2つの計算をしています。足し算の結果を参照渡しで、かけ算の結果を戻り値で返しています。
Integer型の変数sumの値は0(ゼロ)でしたが、func4が呼び出されたあとは値が5に変わっています。Functionプロシージャは1つの値しか戻り値として返すことができませんが、このようにByRef句を使って参照渡しをすることで複数以上の処理結果を取得することができます。
戻り値にオブジェクトを指定する方法
これまでは戻り値が値でしたが、オブジェクトを戻り値として返すこともできます。オブジェクトを戻り値とする場合はSetステートメントを使用します。
以下のようにして記述します。
Function プロシージャ名(引数) As 戻り値のオブジェクト型 Set プロシージャ名 = オブジェクト End Function
それではサンプルコードで確認しましょう。
Sub macro5() Dim str As String Dim range As range str = "A1" Set range = obj(str) range.Value = "Hello VBA!" End Sub Function obj(ByVal str As String) As range Set obj = range(str) End Function
実行結果:
このサンプルコードではFunctionプロシージャobjの戻り値の型にオブジェクト型のrangeを指定しています。Setステートメントを使ってobjに代入しています。またobjを呼び出す際にもSetステートメントを使っています。
引数、戻り値に配列を指定する方法
引数に配列を指定する場合には引数名の後に「()」(カッコ)を付けます。
なお、引数に配列を指定する場合は全て参照渡しになります。これは引数に配列を指定する場合、先頭のアドレスを渡しているためで値を渡すようにはなっていないからです。
また戻り値に配列を指定する場合には戻り値のデータ型の後に「()」(カッコ)を付けます。
以下のような記述になります。
Function プロシージャ名(配列名() As データ型) As 戻り値のデータ型() プロシージャ名 = 戻り値 End Function
それでは実際の使い方をサンプルコードで確認しましょう。
Sub macro6() Dim i As Integer Dim arr(3) As Integer ' 配列の要素の初期化 For i = LBound(arr) To UBound(arr) arr(i) = i Next i ' 配列を戻り値とするFunctionプロシージャの呼び出し ReDim new_arr(3) As Integer new_arr = myArray(arr) ' 出力表示用に配列の要素を取得 Dim str As String For i = LBound(new_arr) To UBound(new_arr) str = str & new_arr(i) & vbCrLf Next i MsgBox str, vbInformation End Sub Function myArray(arr() As Integer) As Integer() Dim i As Integer For i = LBound(arr) To UBound(arr) arr(i) = arr(i) + 10 Next i myArray = arr End Function
実行結果:
このサンプルコードではFunctionプロシージャmyArrayで引数と戻り値にInteger型の配列を指定しています。また「myArray」を呼び出し代入するためにReDim動的配列new_arrを定義しています。
なおサンプルコードでは配列の要素数を調べるためにLBound関数とUBound関数を使用しています。
LBound関数は引数に指定した配列で使用できる最も小さいインデックス番号を返します。UBound関数は引数に指定した配列で使用できる<最も大きいインデックス番号を返します。
VBAの関数について
VBAには元々用意されている関数もあります。VBAで用意されている関数については、こちらのサイトで詳しく解説しています。ぜひ参考にしてください。
VBAの将来性
このように思っている人は多いでしょう。
VBAの用途はさまざまで、
- VBAのスキルがあれば転職できるのでは?
- 業務効率化のスキルは需要が高そうだから
などが上げられます。確かに、業務効率化はどこの企業も目指していて、需要が高いように見えます。ただ、VBAを扱えることが強みになるかといわれると、すこし疑問があります。
VBAは基本的にエクセル上でしか使用することができません。しかし、最近では社内書式をスプレッドシートで管理している企業も増えており、今後エクセル自体の需要が少なくなってしまう可能性も考えられます。
そうなってしまうと、VBAを習得しても活躍の場が限られてしまいますよね。そう考えると将来的にVBAの需要はあまり高くないといえます。
ではVBAを学んでいる人はどうすればいいのでしょう。VBAの将来性や今後の対策などをこちらの記事でまとめているのでぜひご確認ください。
まとめ
ここでは、Functionプロシージャについて説明しました。
値や参照での引数渡し、戻り値が値やオブジェクトの場合、引数・戻り値が配列の場合などいろいろな内容をお伝えしましたが、どれも使う機会が多いものばかりではないかと思います。
使いこなすことができるように、この記事を何度も参考にして下さいね!