VBAの処理は作ったことあるけど、オリジナル関数がわからない・・・
関数の種類や、具体的なオリジナル関数の作り方を知りたいな・・・
マクロの記録や簡単なSubプロシージャを作ってVBAを書いたことがある人は多いですが、関数を使いこなしてツールを作っている人は少ないです。VBAを本格的に力を入れて学習している人は別ですが、ちょっとした作業を自動化するためにVBAを使った人はわからないことも多いのではないでしょうか。
こんにちは!フリーランスエンジニア兼テックライターの脇坂です。
この記事では、関数を覚えてVBAをより使いこなしていきたい方向けに、VBAの関数の種類・メリット・作り方について解説します!
また、単純に関数の作り方を解説するだけでなく、関数を使うメリット・具体的な用途なども解説しています。関数を使いこなすための方法を全てまとめて解説しているため、ぜひ見てみてくださいね!
この記事はこんな人のために書きました。
- 簡単なSubの処理を作ったことはあるが、Functionを使ったことがない人
- 関数の使い方・メリット・具体的な用途をイメージできない人
VBAの関数とは?
最初に、関数について簡単に解説します。
関数とは、実行後に結果を返してくれる処理のことです。例えば、A + Bの計算結果、条件に一致したときの文字列、エラー結果などを返すことができます。
VBAやExcelでもともと作られている関数や、オリジナルの関数を作ることもできます処理を作ることもできます。使いこなすとVBAのツールが作りやすくなるため、使い方を覚えておくととても便利です!
VBAの関数の種類
次に、VBAの関数の種類について解説します。
VBAで使える関数は、大きく分けて以下の3つのタイプがあります。
■VBAの関数の種類
- VBA関数
- ワークシート関数
- Function関数
それぞれ詳しく解説しますね。
VBA関数
1つ目は、VBA関数です。
VBAを書くときに最初から使える関数で、処理を簡単に作るための便利機能です。たとえば金額の計算をする場合、数値の切り上げ・切り捨ての指定は重要ですよね。VBAに最初からあるRoundUp(切り上げ)、RoundDown(切り捨て)を使うことで簡単に切り上げ・切り捨てを指定することができます。
これを1から計算式を作って作ろうとすると、作るだけでなく、正しく計算されるかテストに時間がかかってしまいますよね。VBAでは、このように便利な関数が最初からあります。
「計算式を作ろう」と思ったときは、既に関数がないか調べてから作るのがおすすめです。
ワークシート関数
2つ目は、ワークシート関数です。
ワークシート関数とは、Excelのセルで使える関数のことです。Sum、If、Count、SumIf、Vlookupなど、Excelで便利な関数は多いですよね。VBAでは、Excelで使える関数を計算に使うことができます。
WorksheetFunction.関数名のように書くことで、Excelのセルと同じように関数を使うことができます。
ただ、これだけ見ても使い方のイメージが湧かない方もいるともうので、Vlookup、CountIfの書き方をまとめた記事をご紹介します。以下を見つつ、実際に使ってみるのがおすすめです!
Function関数
3つ目は、Function関数です。
VBA関数、ワークシート関数は既存の関数を使う方法でしたが、Function関数は自作する関数です。Subと同じような感覚で、関数を作ることができます。
Subとの大きな違いは、結果を返せることです。A + Bの結果、条件に一致した文字列、エラー結果などを返せるようになるため、開発が楽になるだけでなく、開発後の修正もしやすくなるのが特徴です。
次章で、Function関数の作り方・使い方について、詳しく紹介します。
VBAのFunction関数の作り方・実行方法
次に、Function関数の作り方・実行方法について解説しますね。
わかりやすく解説するために、Subの作り方と比較して解説します。
Subの作り方:
Sub マクロ名(引数) 'ここにマクロ実行時の処理を書く End Sub
Subのサンプル:
Sub サブのマクロサンプル() '計算用の変数用意 Dim totalNum_Man As Integer Dim totalNum_Woman As Integer Dim scoreMan1 As Integer '男子生徒1の点数 Dim scoreMan2 As Integer '男子生徒2の点数 Dim scoreMan3 As Integer '男子生徒3の点数 Dim scoreWoman1 As Integer '女子生徒1の点数 Dim scoreWoman2 As Integer '女子生徒2の点数 Dim scoreWoman3 As Integer '女子生徒3の点数 Dim scoreWoman4 As Integer '女子生徒4の点数 Dim scoreAvgMan As Integer '男子生徒の平均点数 Dim scoreAvgWoman As Integer '女子生徒の平均点数 '生徒の点数 scoreMan1 = 60 scoreMan2 = 76 scoreMan3 = 34 scoreWoman1 = 80 scoreWoman2 = 88 scoreWoman3 = 76 scoreWoman4 = 92 '平均点数計算 scoreAvgMan = (scoreMan1 + scoreMan2 + scoreMan3) / 3 scoreAvgWoman = (scoreWoman1 + scoreWoman2 + scoreWoman3 + scoreWoman4) / 3 '計算結果を表示 MsgBox "男子生徒の平均点数:" & scoreAvgMan & vbCrLf & _ "女子生徒の平均点数:" & scoreAvgWoman End Sub
実行結果:
男子生徒、女子生徒の点数をそれぞれ変数に格納し、平均点数を計算した結果をメッセージで表示するサンプルです。ただ、このサンプルは1つ誤りがあります。
scoreAvgWoman = (scoreWoman1 + scoreWoman2 + scoreWoman3 + scoreWoman4) / 3
以下女子生徒の平均を計算する処理を、3で割ってしまっています。男子生徒の人数が3人だったため、そのコードをコピーしてカッコの人数だけ追加してしまうと、このようにミスが起こってしまいます。
続けて、Functionにした場合の例を見てみましょう。
Functionの作り方:
Function 関数名(引数) as 結果を返す値の型名 End Function
Subと比較すると、関数名の後ろに「as 結果を返す値の型名」を入れているのが特徴ですね。さきほどのサンプルをFunctionを使った場合は次のようになります。
Functionのサンプル:
'平均点数の結果をメッセージ表示する処理 Sub マクロサンプル() '計算用の変数用意 Dim totalNum_Man As Integer Dim totalNum_Woman As Integer Dim scoreListMan(1 To 3) As Integer '男子生徒の点数リスト Dim scoreListWoman(1 To 4) As Integer '女子生徒の点数リスト Dim scoreAvgMan As Integer '男子生徒の平均点数 Dim scoreAvgWoman As Integer '女子生徒の平均点数 '生徒の点数 scoreListMan(1) = 60 scoreListMan(2) = 76 scoreListMan(3) = 34 scoreListWoman(1) = 80 scoreListWoman(2) = 88 scoreListWoman(3) = 76 scoreListWoman(4) = 92 '平均点数計算 scoreAvgMan = calcAvgScore(scoreListMan) scoreAvgWoman = calcAvgScore(scoreListWoman) '計算結果を表示 MsgBox "男子生徒の平均点数:" & scoreAvgMan & vbCrLf & _ "女子生徒の平均点数:" & scoreAvgWoman End Sub '生徒の数分点数をまとめた配列を引数に渡し、平均値を計算する処理 Function calcAvgScore(ScoreList() As Integer) As Integer 'スコアの数を計算 Dim scoreNum As Integer 'スコアの数 scoreNum = UBound(ScoreList) '合計値を計算 Dim totalScore As Integer: totalScore = 0 '合計値 Dim i As Integer For i = 1 To scoreNum totalScore = totalScore + ScoreList(i) Next i '平均点数(合計値 ÷ スコア人数)を戻り値に設定 calcAvgScore = totalScore / scoreNum End Function
実行結果:
平均点数を計算した結果を返すFunction関数「calcAvgScore」を用意し、計算に使っています。スコア用に作成した配列の数を合計人数として計算しているため、合計人数を間違えてしまうリスクがなくなりました。
Function関数を使っているサンプルマクロ2も、以下のように計算を書くコードがシンプルになっています。
'平均点数計算 scoreAvgMan = calcAvgScore(scoreListMan) scoreAvgWoman = calcAvgScore(scoreListWoman)
計算ミスを減らすだけでなくメインの処理もシンプルにすることができるので、使い方を覚えておくととても便利です。
VBAのFunction関数を使うメリット・具体的な用途とは?
次に、Function関数を使うメリット・具体的な用途について解説します。
計算結果を返すとき
1つ目は、計算結果を返すときです。
先ほどサンプルで解説したように計算結果を返すことができるため、次のようなメリットがあります。
■計算結果を返すことによるメリット
- 計算方法を手入力するときに比べてミスが減る
- 計算するメインの処理がシンプルになる
- 計算式が変わった場合も、Function関数の修正だけで済む
最後のメリットだけ今まで解説していなかったため、少し補足しますね。Subのみで処理を書いていた場合、計算式が変わった時に「計算式以外の処理」を間違えて直してしまうリスクがあります。
修正している最中に、他の処理の間違いを見つけて直してしまうことや、修正中に誤って直したことに気づかないケースはよくあります。修正した結果良くなることもありますが、バグの原因になってしまうときもあります。
Function関数にわけておくことで、誤って他の処理を書き換えてしまうリスクが減りますよね。メンテナンス性を高めるためにも、Function関数はとてもおすすめなのです。
エラー結果を返すとき
2つ目は、エラー結果を返すときです。
計算結果を返すだけでなく、処理のエラーの有無を確認する目的で結果を返すことができます。たとえば、エラー情報が文字列が返ってきたときだけ、エラー処理を入れるような処理を作ることができます。
エラーを返す例は言葉だけではわかりにくいので、例を簡単に解説しますね。
サンプルコード:
Sub メイン処理() Dim resultMessage As String resultMessage = Func1 If resultMessage <> "" Then MsgBox "エラーが発生しました。" & vbCrLf & _ "システム管理者に以下問い合わせてください。" & vbCrLf & _ "------------------------------------------------------------" & vbCrLf & _ Func1 & vbCrLf & _ "------------------------------------------------------------", vbCritical End If End Sub 'エラーが出たときにエラー情報を返す関数の例 Function Func1() As String On Error GoTo Func1_Err Func1 = "" Dim intA As Integer intA = 100000000 Exit Function Func1_Err: Func1 = "エラー場所:Module1.Func1" & vbCrLf & _ "エラー番号:" & Err.Number & vbCrLf & _ "エラー詳細:" & Err.Description End Function
実行結果:
Function関数「Func1」の処理で、Integer型の変数に桁あふれが起こる数値を入れることで、意図的にエラーを発生させています。on Error Goto文を使い、エラーが発生したときにエラー場所(モジュール名 + 関数名)、エラー番号、エラー詳細を文字列で返すようにしており、メイン処理で戻り値が空白でないときだけエラー処理を入れています。
エラーが起きた箇所、エラーの原因などがわかりやすくなるので、関数を作るときはこの方法がおすすめです!
ちなみに、エラー処理については以下でも詳しく解説しているため、気になる方は見てみてくださいね。
まとめ
今回は、VBAの関数の種類・メリット・作り方について解説しました。
VBAの関数の種類を覚えるだけでなく、Function関数の作り方やメリットを覚えておくととても便利です!
ぜひ、使ってみてくださいね!