【VBA入門】Functionの使い方(呼び出し、引数、戻り値)

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

実行結果:
HelloVBA

このサンプルコードでは、戻り値なしで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

実行結果:
HelloVBA

このサンプルコードでは、戻り値のデータ型が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

実行結果:
3^2=9

このサンプルコードでは、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

実行結果:
2x3=6

このサンプルコードでは、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

実行結果:
2+3=5, 2x3=6

このサンプルコードでは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

実行結果:
range_HelloVBA

このサンプルコードでは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

実行結果:
array

このサンプルコードではFunctionプロシージャmyArrayで引数と戻り値にInteger型の配列を指定しています。また「myArray」を呼び出し代入するためにReDim動的配列new_arrを定義しています。

なおサンプルコードでは配列の要素数を調べるためにLBound関数とUBound関数を使用しています。

LBound関数は引数に指定した配列で使用できる最も小さいインデックス番号を返します。UBound関数は引数に指定した配列で使用できる<最も大きいインデックス番号を返します。

VBAの関数について

VBAには元々用意されている関数もあります。VBAで用意されている関数については、こちらのサイトで詳しく解説しています。ぜひ参考にしてください。

VBAの将来性

VBAのスキルを学んで業務を効率化したい

このように思っている人は多いでしょう。

VBAの用途はさまざまで、

  • VBAのスキルがあれば転職できるのでは?
  • 業務効率化のスキルは需要が高そうだから

などが上げられます。確かに、業務効率化はどこの企業も目指していて、需要が高いように見えます。ただ、VBAを扱えることが強みになるかといわれると、すこし疑問があります。

VBAは基本的にエクセル上でしか使用することができません。しかし、最近では社内書式をスプレッドシートで管理している企業も増えており、今後エクセル自体の需要が少なくなってしまう可能性も考えられます。

そうなってしまうと、VBAを習得しても活躍の場が限られてしまいますよね。そう考えると将来的にVBAの需要はあまり高くないといえます。

ではVBAを学んでいる人はどうすればいいのでしょう。VBAの将来性や今後の対策などをこちらの記事でまとめているのでぜひご確認ください。

まとめ

ここでは、Functionプロシージャについて説明しました。

値や参照での引数渡し、戻り値が値やオブジェクトの場合、引数・戻り値が配列の場合などいろいろな内容をお伝えしましたが、どれも使う機会が多いものばかりではないかと思います。

使いこなすことができるように、この記事を何度も参考にして下さいね!

この記事を書いた人

【プロフィール】
DX認定取得事業者に選定されている株式会社SAMURAIのマーケティング・コミュニケーション部が運営。「質の高いIT教育を、すべての人に」をミッションに、IT・プログラミングを学び始めた初学者の方に向け記事を執筆。
累計指導者数4万5,000名以上のプログラミングスクール「侍エンジニア」、累計登録者数1万8,000人以上のオンライン学習サービス「侍テラコヤ」で扱う教材開発のノウハウ、2013年の創業から運営で得た知見に基づき、記事の執筆だけでなく編集・監修も担当しています。
【専門分野】
IT/Web開発/AI・ロボット開発/インフラ開発/ゲーム開発/AI/Webデザイン

目次