まずざっくり:「Sub」と「Function」の一番大きな違い
一言で言うと、こうです。
Sub
「何か処理をするだけの手順」
結果(値)を“返さない”タイプのプロシージャ
Function
「何か処理をして、その結果を“値として返す”手順」
関数として値を返すプロシージャ
ここが本質です。
「値を返すかどうか」――この一点だけで、Sub と Function を見分けられるようになると、かなりスッキリします。
Subとは何か:結果を返さない「手順」
Subの役割をイメージでつかむ
Sub は、「これをやって」「あれもやって」と、Excelに対して命令を並べた“作業手順”です。
実行すると、セルを書き換えたり、メッセージを出したり、シートをコピーしたりしますが、
「この値を返します」という形では結果を返しません。
Excel側から見ると、
「呼び出したら何かしてくれるけど、値としては何ももらわない」
そんな“お仕事係”が Sub です。
Subの基本形
形はこうです。
Sub プロシージャ名()
' ここに処理を書く
End Sub
VB例として、メッセージを出すだけの Sub を書いてみます。
Sub あいさつ()
MsgBox "こんにちは!"
End Sub
VBこの Sub を実行すると、メッセージボックスが出るだけで、
「戻り値」というものはありません。
典型的なSubの使いどころ
例えば、次のような処理は、ほとんど Sub で書きます。
・セルに値を書き込む
・書式を整える
・シートを追加・削除する
・ファイルを開く・保存する
・ボタンを押したときに一連の処理を行う
「Excelの状態を変えること自体が目的」のときは、Sub がしっくりきます。
Functionとは何か:値を返す「関数」
Functionの役割をイメージでつかむ
Function は、「何かを計算して、その結果を“値として返す”」ためのプロシージャです。
Excelのワークシート関数(SUM、AVERAGE など)と同じイメージで考えると分かりやすいです。
呼び出し側から見ると、
「このFunctionを呼ぶと、計算結果が一つ“値として”返ってくる」
その値を、セルに入れたり、他の計算に使ったりできます。
Functionの基本形
形はこうです。
Function 関数名(引数...) As 型
' 計算などをして
関数名 = 戻したい値
End Function
VB一番大事なのは、
「Function名に値を代入することで“戻り値”を決める」
というルールです。
簡単なFunctionの例
例えば、二つの数値の合計を返す Function を作ってみます。
Function AddTwoNumbers(a As Long, b As Long) As Long
AddTwoNumbers = a + b
End Function
VBこの Function は、呼び出すと「a + b の結果」を返します。
VBAの中からなら、こう使えます。
Sub Test()
Dim result As Long
result = AddTwoNumbers(10, 20)
MsgBox result ' 30 が表示される
End Sub
VBワークシートからも、ユーザー定義関数として使えます。
セルに=AddTwoNumbers(10,20)
と入力すると、セルに 30 が表示されます。
ここが Sub との決定的な違いです。
Sub はセルに直接書き込むなど「外側を変える」のが得意で、
Function は「値を返して、呼び出し側に判断を委ねる」のが得意です。
SubとFunctionの違いを整理して深掘り
違い1:戻り値があるかどうか(最重要)
Sub
戻り値を持たない。
呼び出し側に「値として」何かを返すことはできない。
Function
戻り値を持つ。
Function名に代入した値が、そのまま戻り値になる。
この違いが、設計の分かれ目になります。
「この処理の結果を、どこかで“値として使いたい”か?」
と自分に問いかけて、Yes なら Function、No なら Sub が基本の考え方です。
違い2:ワークシートから直接呼べるか
Sub
ワークシートのセルから =Sub名() のように呼ぶことはできません。
マクロとして実行するか、他のVBAコードから呼び出します。
Function
条件を満たしていれば、ワークシート関数としてセルから呼べます。=関数名(引数...) の形で使えるので、「自作の関数」を作るイメージです。
「セルに直接使いたい処理」は Function 一択になります。
違い3:呼び出し方の書き方
Sub を他のプロシージャから呼ぶときは、こう書きます。
Call あいさつ
' または
あいさつ
VBFunction を呼ぶときは、「値を受け取る」形で書きます。
Dim x As Long
x = AddTwoNumbers(10, 20)
VBSub は「命令」、Function は「値を返す式」として扱われる、という感覚です。
同じ処理をSub版とFunction版で比べてみる
例題:合計を出してメッセージに表示する
まずは Sub だけで書いたバージョンです。
Sub ShowTotal_Sub()
Dim a As Long
Dim b As Long
Dim total As Long
a = 10
b = 20
total = a + b
MsgBox "合計は " & total & " です"
End Sub
VBこの Sub は、「合計を計算して、その場でメッセージを出す」までを全部自分でやっています。
戻り値はありません。
次に、「計算する部分だけ Function に切り出す」バージョンです。
Function GetTotal(a As Long, b As Long) As Long
GetTotal = a + b
End Function
Sub ShowTotal_Function()
Dim total As Long
total = GetTotal(10, 20)
MsgBox "合計は " & total & " です"
End Sub
VBここでは、
GetTotal が「合計を計算して値を返す役」
ShowTotal_Function が「その値をどう使うか決める役」
に分かれています。
この分け方のメリットは、
「GetTotal は、他の場所からも再利用できる」
という点です。
例えば、別の Sub からもこう呼べます。
Sub WriteTotalToCell()
Range("A1").Value = GetTotal(5, 7)
End Sub
VB同じ「合計を出す処理」を、メッセージに出したり、セルに書いたり、好きな形で使い回せるようになります。
いつSubで、いつFunctionにするかの判断基準
基本の問い:「結果を値として使いたいか?」
一番シンプルな判断基準はこれです。
結果を「値として」どこかに渡したいか?
Yes → Function
No(その場でセルを書き換える、メッセージを出すなどで完結) → Sub
例えば、
合計を計算して、その場でメッセージに出すだけ
→ Sub でも Function でも書けるが、Sub で完結させてもよいケースが多い。
合計を計算して、その値をセルに入れたり、別の計算に使ったりしたい
→ Function にしておくと、再利用しやすくなる。
「副作用」と「純粋な計算」を分けて考える
もう一歩踏み込むと、
「Excelの状態を変える処理(副作用)」と
「値を計算するだけの処理(純粋な計算)」
を分ける、という考え方があります。
セルを書き換える、シートを追加する、ファイルを保存する――こういうのは副作用です。
これは Sub に任せるのが基本です。
一方で、「二つの数値の合計」「税抜き金額から税込み金額を出す」などは純粋な計算です。
これは Function にしておくと、どこからでも呼び出せて、テストもしやすくなります。
超初心者のうちは、
「Excelを直接いじるのは Sub」
「計算だけなら Function にしてみる」
くらいの感覚で十分です。
まとめ:SubとFunctionを“使い分けられる人”になる
ここまでのポイントをぎゅっとまとめると、こうなります。
Sub
結果を値として返さない「手順」。
セル操作や画面表示など、「Excelの状態を変える処理」をまとめるのに向いている。
Function
結果を値として返す「関数」。
計算結果や判定結果を返し、それを呼び出し側で自由に使える。
ワークシート関数としてセルからも呼べる。
次の練習としておすすめなのは、こんな流れです。
1つ目:今まで Sub だけで書いていた「合計を出す処理」を、Function に切り出してみる。
2つ目:その Function を、メッセージ表示用の Sub と、セル書き込み用の Sub の両方から呼んでみる。
3つ目:余裕があれば、その Function をワークシートから =関数名() で呼んでみる。
「処理を“値を返す関数”として切り出せるようになる」と、コードの組み立て方のレベルが一段上がります。
