VBA

FunctionはSubで代用可能か?それでもFuctionを使ったほうがいい理由

記事内に商品プロモーションを含む場合があります

このページでわかること

SubとFunctionの違いは?使い分けはどうすればいいのかわかります。

覚えること
  1. SubもFunctionもほぼ変わらず処理はできる。
  2. 以下の違いがある
    プログラムの起動方法(Functionは単独では起動できない)
    戻り値の扱い(Subは基本無し、Functionは有り)
  3. 戻り値を必要とする処理は積極的にFunctionを使ってプロシージャを分割する方が可読性が上がる

こんにちは、hokkyokunです。
みなさんはFunctionプロシージャを使う派ですか?
それともSubプロシージャを使い倒す派ですか?

私はどちらかというとSubを使う派でしたが、
プログラムを書いているうちに必要に差し迫り、Functionも使うようになってきました。

どういったときに使うべきか
SubとFunctionごちゃごちゃしてますので、一緒に整理していきましょう。

SubとFunctionの違いは?

一般的な解釈は。。。

  • プログラムの起動
  • 戻り値の扱い

  • に違いがあると考えられます。

    プログラムの起動

    プログラムの起動はそれ単独で動かすことはできません。
    例えばエクセルの上部タブの「開発タブ」からマクロをうごかしてみましたが、Functionを直接動かすことはできませんでした。

    下記のようにSubとFunctionを作っています。

    Subしか表示されません。

    戻り値の扱い

    戻り値については以下のような特徴があります。

    戻り値の特徴

  • Subは戻り値の設定が容易でない
  • Functionは戻り値の設定が容易

  • この「容易」というのがミソで厳密にはSubでも戻り値(のようなもの)は設定可能です。

    ※戻り値とは何かの処理をして計算したあとの結果です。

    例えば、
    数値を二乗するマクロをSubだけで作ってみます。
    プロシージャを「出力プロシージャ」と「計算プロシージャ」に分けて処理することを考えて見ます。

    Sub 出力()
    Dim n As Integer
    n = 3
    Call 計算(n)
    MsgBox ("計算は:" & n)
    End Sub
    
    
    Sub 計算(ByRef n As Integer)
    n = n * n
    End Sub

    処理をすると無事9となります。

    これは何が起こっているかというと

    1. 出力プロシージャでnに3を代入します。
    2. Callで計算プロシージャを呼び出し、byRefで値を渡します。
    3. byRefで渡すので渡した側のプロシージャ(ここでは計算プロシージャ)の計算結果を反映させます
    4. 最後に出力プロシージャで反映された結果を出力します。

    Functionを使う理由は同じような処理を別のプロシージャとして分割し、
    プログラムの可読性を高め、メンテナンスをよくする事だと思いますが、
    Subだけでも作ることは可能に見えます。

    やはりFunctionは必要

    Subでも代用できると思いますが、やはりFunctionはうまく使っていく必要があります。

    比べてみましょう

    1. 上記のように出力と計算のプロシージャを分ける
    2. さらに出力プロシージャで一つ処理を加えなければいけない場合を想定

    具体的には
    計算プロシージャで二乗計算し、
    出力プロシージャでその計算結果に1を足した値をmsgboxで表示させます。

    先ずSubのみで作った場合

    Sub 出力()
    Dim n As Integer
    n = 3
    Call 計算(n)
    MsgBox ("3の二乗に1を足したら、" & n + 1)
    
    n = 4
    Call 計算(n)
    MsgBox ("4の二乗に1を足したら、" & n + 1)
    End Sub
    
    
    Sub 計算(ByRef n As Integer)
    n = n * n
    End Sub

    処理を単純化すると

    1. nに代入
    2. callで呼び出して計算
    3. 計算後のnを使って処理+msgbox

    なんだか処理がもっさりしていますね

    次はSubとFunctionを使ってみましょう

    Sub 出力F()
    Dim n As Integer
    n = 3
    MsgBox (n & "の二乗に1を足したら、" & calc(n) + 1)
    
    n = 4
    MsgBox (n & "の二乗に1を足したら、" & calc(n) + 1)
    End Sub
    
    
    Function calc(n)
    calc = n * n
    End Function

    こちらは

    1. nに代入
    2. Functionで計算とその後の処理+msgbox

    処理をスマートにかつ、何をやっているか非常にわかりやすいと思います!

    今回は単純なモデルなのでたったの1行ですが、これが複雑かつ何回も呼び出すとなると可読性は如実に変わってくると思います!

    まとめ

    FunctionはSubで代用することは可能です。
    ByRefで値を変数を通じて渡し、計算された変数をもらうやり方です。

    ただし、特別な理由がないかぎりおすすめしません。

    理由はコードが長く、何をやっているのかよくわからなくなるためです。
    一方、Functionを使うと処理が一目でわかり、コードも短くなります。

    私もあまり使う機会がなく、軽視していたのですが、
    どんどんFunctionをつかってコードをすっきりさせていこうと思います。

    ではでは。