子どもの”プログラミング的思考"をグングン伸ばす本

ExcelVBAの解説

プロシージャの種類

VBAには、2種類のプロシージャがあります。SubプロシージャとFunctionプロシージャです。

  1. Subプロシージャとは
  2. Sub で始まるプロシージャを指します。いままで解説してきたプロシージャですね。例えば次のようなプロシージャです。

    Sub ShowMyName()
        MsgBox "僕の名前はTatsudaiです"
    End Sub
    

    Subプロシージャには、処理を記述します。あいまいな言い方ですね。でも、次に説明するFunctionプロシージャを理解すると、その意味が分かります。

    まとめ

  3. Functionプロシージャとは
  4. このプロシージャは、Functionで始まります。例えば次のようなプロシージャです。

    Function getTomorrow() As Date
        getTomorrow = Date + 1
    End Function
    

    Function で始まるので、最終行は End Function で終わります。

    ここで一番大切なことを言います。Functionプロシージャは、戻り値を持ちます。戻り値とは、答えのことです。

    つまり、Function とは関数のことなんです。(そのまんまです)

    Functionプロシージャの構文は次の通りです。

    Function 関数名() As データ型

     関数名 = 戻り値

    End Function

    コードの中で必ず戻り値の設定をおこないます。上記のサンプルコードでは、getTomorrow = Date + 1 の部分です。

    ちなみに、Date は、今日の日付を返す(答えとして出すことを「返す」といいます)VBA用の関数です。今日の日付に1を足すので、明日の日付になります。

    そう、このFunction プロシージャ getTomorrow は、明日の日付を返す関数となります。

    日付が戻り値なので、データ型はDate になります。新しいデータ型を覚えましたね。(これで、Integer , String , Date の3つを取り上げましたよ)

    まとめ

  5. Functionプロシージャの使い方
  6. 答えを出すのがFunctionプロシージャなので、Subプロシージャの中で使ってもらう必要があります。

    Sub showTomorrow()
        Range("C2").Value = getTomorrow
    End Sub
    

    セルC2に、Functionプロシージャ getTomorrow の戻り値を設定しています。このSubプロシージャを実行すると、次のようになります。

    今日は2/24 なので明日は 2/25 になります。このプロシージャを実行する日によってもちろん明日は変わってきます。念のため。

    まとめ

  7. 引数を持つFunctionプロシージャがあります
  8. Excelの関数を思い浮かべてください。例えば、合計を出すSum関数は、必ず引数(ひきすう)を指定します。指定しないと、いくら頭のいいExcelでも合計を出すことができないからです。だって、どの合計を出したらいいのか 分からないのですから、答えの出しようがありませんよね。

    言い換えると、受け取った引数の値に応じて、柔軟に答えを出すことができるのです。これって便利なことですよね。

    Functionプロシージャも、引数を持つことができます。そのプロシージャは、受け取った引数の値に応じて答えを出します。

    そんなFunctionプロシージャを作ってみましょう。

    Function getNextMonth(mydate As Date) As Integer
        Dim d As Date
        d = DateAdd("M", 1, mydate)
        getNextMonth = Month(d)
    End Function
    

    このプロシージャは、Date型(日付型)の引数を受け取って、その引数の翌月の数字を返す関数です。なお、日付を返すわけではなく数字を返すので戻り値のデータ型は Integer です。

    引数には、適当な名前を付けておくのがルールです。今回はmydate としました。引数名には、変数名の命名ルールが適用されます。

    それでは、コードの説明をしておきましょう。

    Date型の変数d を宣言して、d にDateAdd関数の答えを代入しています。

    DateAdd関数は、VBAの関数で、基準日に日付を加算した日付を返します。最初の引数に単位(今回は月を示すM)、2番目の引数には加算する数(今回は1)、そして3番目の引数には基準となる日付を指定します。今回は、基準日に1ヵ月を加算した日を返します。

    3番目の引数にはFunctionプロシージャの引数mydate を指定しているので、mydateの値によって答えが決まります。

    そして、プロシージャの戻り値には、変数d の月を取り出して設定しています。Month関数は、VBAの関数ですが、Excelの関数と同じように使えます。

    さて、それでは、問題です。以下のようなシートがあります。セルC4には記念日の日付が入力されています。ただし、ひとによってこの日付は変わってきます。とりあえず2017/3/19 が入力されているとして、セルC5に記念日の翌月の数字を表示したいとします。どのようなプロシージャを作ればいいでしょうか?

    Functionプロシージャ getNextMonth の出番ですよ。正解例を紹介します。(正しく動作すれば正解なので、書き方はいくつもありますが)

    Sub showNextMonth()
        Dim dt As Date
        dt = Range("C4").Value
        Range("C5").Value = getNextMonth(dt)
    End Sub
    

    日付型の変数dt を宣言し、dt にセルC4の値を代入しています。そして、Functionプロシージャ getNextMonth の引数にdt を渡し、戻り値をセルC5に設定(表示)しています。

    さて、FunctionプロシージャgetNextMonth の引数のことを仮引数(かりひきすう)といいます。mydate という名前を付けましたね。

    Functionプロシージャを実際に使用するときに受け取る引数を実引数(じつひきすう)といいます。dt という名前の変数を引数に設定していますね。

    このように、借り引数の名前と実引数の名前は別に一致しなくても構いません。重要なのは、引数のデータ型が一致しているかどうか、だけです。

    実行結果は以下の通りです。なお、セルC4には、2017/3/19が入力されているものとします。

    セルC5には、翌月の 4 が表示されていますね。セルC4の日付を自由に変更して、プロシージャ showNextMonth を再度実行してみてください。ちゃんと翌月の数字が表示されますよ。引数を持つFunctionプロシージャは、柔軟な使い方ができます。

    正解例をもう一つ紹介しておきましょう。

    Sub showNextMonth()
        Range("C5").Value = getNextMonth(Range("C4").Value)
    End Sub
    

    Functionプロシージャの引数に、ずばりセルC4の値を設定しています。これもOKです。1行で済んでしまいましたね。

    コーディングのスタイルは色々あります。自分の思う通りに書いてください。経験とともにスタイルは変化していきます。そうやって分かりやすいコーディングが身についていきます。他人のコードも参考になります。やがていろんなことに気付くようになります。自分なりのよりよいスタイルを築いていってください。

    少し話がそれますが、この記事も、僕のスタイルが出ています。ですから、他の方が書いた解説もぜひ読んでください。アプローチの仕方や視点が異なっているはずです。同じことを説明していても、表現が違ってきます。多面的に捉えることができるので、勉強になると思います。

    さて、話をもとに戻します。Functionプロシージャの構文は、グレードアップしてこうなりました。

    Function 関数名(仮引数名 As データ型) As データ型

     借り引数を使って、戻り値を求めるために必要な処理をおこなう

     関数名 = 戻り値

    End Function

    Functionプロシージャを覚えると、Subプロシージャのことも分かってきます。戻り値のないプロシージャがSubプロシージャということになりますね。つまり、Subプロシージャは処理をするだけなのです。

    まとめ