再帰関数  Macユーザー向け Excel VBA 入門 [07] Excel2019 for Mac

Recursive function(Png)

[07] Excel 再帰関数の作成

 C言語みたいに「再帰」を利用したユーザー定義関数を作成してみよう!

「階乗」関数の自作(ユーザー定義関数2)

再帰関数とは?
・【おまけ】VBA「無限ループ(無応答)」対処方法のまとめ
ByRef (参照渡し)ByVal (値渡し)

(注) 学習のために作成するだけで、既に Excel には「階乗」を実装した FACT関数 が用意済み。




 Macユーザー向け Excel VBA 入門 [07] 再帰関数の作成 

 まず、Excel メニューバーの [ヘルプ] - [更新プログラムのチェック] にて、適用されていないアップデートがあれば行ってください。

 C言語みたいに「再帰」を利用した、ユーザー定義関数を作成してみよう! 

 「階乗」関数の自作(ユーザー定義関数2) 

vba2019_primer[07] 01_png

 前回「ユーザー定義関数」を作成したExcelファイルを開きます。
VBAコードが含まれているため、「マクロを有効」にします!

vba2019_primer[07] 02_png

 Module1 モジュールのVBAコードを表示するため、[開発]タブの [マクロ]ボタンをクリック。
次に前回作成した「マクロ名」を選択し、[編集]ボタンをクリック。

vba2019_primer[07] 03_png

 VBEウィンドウが開き、前回作成した「マクロ」に対応するVBAコードが「コード ウィンドウ」に表示されます!  「コード ウィンドウ」にプロシージャ1つ分のVBAコードしか表示されていない場合は、「コード ウィンドウ」左下の右側のボタンをクリックすると モジュールのコード全体 が表示されます。

 上記画面のように 下記 VBAコード を間違いなく追加で入力するか、(下記コード上でクリックするとコピー用のボタンが右上に表示されるため)コピー後に VBAコード を貼り付け

 「イミディエイト ウィンドウ」上で 追加した FuncTest2() ユーザー定義関数 を実行し、 動作を確認 しましょう。
 ? FuncTest2(3)
入力後に [return] キー押下にて 6 が表示され、 3 * 2 * 1 = 6 で問題ないようです。
 ? FuncTest2(10)
入力後に [return] キー押下にて 3628800 が返され、 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1 = 3,628,800 のため 問題ありません。


Public Function FuncTest2(ByVal n As Long) As Long
Rem
Rem FuncTest2 = n! = n * (n - 1) * (n - 2) * ... * 1
Rem 【Excel関数 FACT(n) 】を実装(VBAコードでもC言語みたいに再帰関数を記述可能)

    If n > 1 Then
        FuncTest2 = n * FuncTest2(n - 1)
    Else
        FuncTest2 = 1  '(n <= 1) に対応するコードを誤って記述すると、無限ループ
    End If

End Function

 再帰関数とは? 

 自分自身を参照可能な状態を「再帰」と言います! その仕組みを利用し、「自分自身の関数」を呼び出し可能な関数を「再帰関数」と呼びます。
「再帰関数」を上手く利用するとコードを簡潔に記述することが可能ですが、終了条件を誤ると「無限ループ」に陥いるためコードの実装には注意が必要です。 (「再帰」の仕組みが利用できないプログラム言語も存在するが VBAを含むVBでも利用可能)

 7行目の FuncTest2 = n * FuncTest2(n - 1) にて再帰呼び出しを行っていますが、前々回学習した If文で「 n の値 」により制限を加えなければ「無限ループ」に陥り終了しません。
今回だと (n <= 1) の場合、関数の返り値として 1 を返して 再帰呼び出しを終了させています。
 引数 n に 10 を指定して呼び出した場合、 10 * FuncTest2(10 - 1) つまり 10 * FuncTest2(9) が実行されます。 順に FuncTest2(2) まで再帰呼び出しが行われ、FuncTest2(1) で 1 が返され「ループ」を終了。

 【おまけ】VBA「無限ループ(無応答)」対処方法のまとめ 

念のため、  VBA「無限ループ」(無応答状態も含む)対処方法  を纏めました!

Mac】キーボードによる VBAの強制終了方法
 (1) [command] + [.](ピリオド)
 (2) [command] + [control] + [esc]
 (3) [esc](2回押し)
 (4) [command] + [option] + [esc] にて、Excel を選択し「アプリケーションの強制終了」を実行

Windows】キーボードによる VBAの強制終了方法
 (1) [Ctrl] + [Pause](または [Break] )
 (2) [Esc]
 (3) 「タスクマネージャー」のプロセスにて Excel を選択し、「強制終了」を実行



vba2019_primer[07] 04_png

 上記画面のように ワークシート上のセル「C1」に =fu など3文字位を入力すると 「ユーザー定義関数」も併せて候補表示されるため FuncTest2 をクリックすると関数名が補完され、 =FuncTest2( と表示されます。

vba2019_primer[07] 05_png

 通常の Excel関数と同様に「A1」セルをクリックすると =FuncTest2(A1 まで補完される。

vba2019_primer[07] 06_png

 [return] キーを押して =FuncTest2(A1) にて確定すると、「C1」セルに「 FuncTest2(1) ユーザー定義関数 」の実行結果が表示されます。

vba2019_primer[07] 07_png

 「C1」セル選択後 [command] + [C] でコピー。

vba2019_primer[07] 08_png

 「C2:C10」セル選択後に [command] + [V] で貼り付けすると、「 引数 n に 2 から 10 を指定した場合の FuncTest2(n) 実行結果 」が各セルに順に表示されます。

vba2019_primer[07] 09_png

 「D1」セルに =fact( 入力後 「A1」セルをクリックし、[return] キーで確定。 ( =FACT(A1) と表示 )

vba2019_primer[07] 10_png

 「D2:D10」セル選択後に [command] + [V] で貼り付けすると、「 引数 n に 2 から 10 を指定した場合の FACT(n) 実行結果 」が各セルに順に表示されます。

vba2019_primer[07] 11_png

 「FuncTest2() ユーザー定義関数」と Excelに元々用意されている「FACT関数」の実行結果が 同一となる事を確認します!

 【復習】条件分岐の If 文(ステートメント)

If (条件A) Then
  ・・・ ' (条件A)に合致するときに  実行される命令(複数行も可)
End If

  あるいは

If (条件A) Then
  ・・・ ' (条件A)に合致するときに  実行される命令(複数行も可)
Else
  ・・・ ' (条件A)に合致しないときに 実行される命令(複数行も可)
End If

(If文の)ネストと呼ばれるが、If文 の中に If文 を記述することも可能。
また、条件分岐には Select Case 〜 ステートメント もありますが、また後日説明いたします。

 ByRef (参照渡し)と ByVal (値渡し) 

 1行目の関数の 引数(パラメーター) n に ByVal というキーワードが付いていることに気付いた方もみえるでしょう。
ByVal は By Value (値渡し)、ByRef は By Reference (参照渡し・ポインタ渡し) の意味で、VBA を含む VB6.0系では 省略すると ByRef 指定 となります。
実は FuncTest2() 関数は ByRef でも結果は変わりませんが、効率を重視して ByVal を選択しました。

 ByRef だと 呼び出し元 と 呼び出し先で同一の変数が使用され、 ByVal だと 呼び出し元 の 変数のコピーが 呼び出し先 にて使用されることを 本日は覚えてください。
ByVal 指定だと変数のコピーが利用されるため、 呼び出し元 の 変数の値は変更されません。

 呼び出し元 の 変数の値が(無意識に)変更されるとバグになりやすいため、 デフォルト ByVal がプログラム言語の主流です。 事実、C# と同じになる様に、 VB.NET ( Visual Basic .NET ) では デフォルトが ByVal に変更されています。

次回は、この指定により結果が異なる場合の例を示します。



 [command] + [Q] にてまず VBE を終了し、Excel のウィンドウ内を選択して [command] + [Q] にて Excel も終了させます。 「作業中のブック」を保存するか確認のダイアログ画面が表示された場合は 「保存」しましょう。 「自動保存」済みの場合、保存するかどうかの確認ダイアログ画面は表示されません。

 次回は、 ByRef (参照渡し)ByVal (値渡し)、この指定により実行結果が異なる場合がある事を学習します!





広告
  
<



Macブログ ランキング アイコン
最後まで読んでいただき、ありがとうございます。 また、お越しくださいませ。
// アタル
For follow LINE Reader Group!Subscribe to this blog on Feedly!

Next Post Previous Post
No Comment
Add Comment
comment url