Chapter 11 分岐構造 ( If )

イントロダクション コース

テーマ

 第11回目となる本稿のテーマは、「条件分岐を表現する構文の一つである If 文を理解する」です。

 本稿からようやくプログラムらしいものを少しずつ書けるようになります。今まで変数、データ型、算術演算、比較演算、論理演算と学習して来ました。これで条件分岐を学習するために必要な知識は整ったと言えます。

 条件分岐の構文は制御構造とも呼ばれます。プログラムの流れを制御する機能をもっているのでそう呼ばれているわけです。本稿では、そうした制御構造のうち条件分岐に焦点をあて、中でも使用頻度の高い If 文について学習を進めていきます。

条件分岐

 条件分岐とは、プログラムが実行される過程において実行コードが条件によって変化することを言います。例えば、従業員の給与情報を処理するプログラムの中で今期の成績によってボーナスの基礎金額が変わるような場合、「今期の成績」が条件となり、「基礎金額を決めるロジック」が条件によって変化することになります。このようにロジックが複数に分岐する箇所を「条件分岐の制御構造」によってコントロールします。みなさんは既に Excel を使用していますので IF あるいは IFS という関数を使った経験があるかもしれません。VBA における条件分岐もそれと同様に機能します。また、まだそれらの関数を使った経験がない方も安心してください。ここでは Excel 関数の知識がなくても VBA の条件分岐を学ぶことが出来ます。

条件

条件式

 条件によってプログラムの流れを分岐させるために必要となるのが条件式です。条件式を満たしているか否かによってコードの流れを分岐させるわけですね。それでは条件式の記述方法から学習を進めていきましょう。以下のマクロを Sheet1 シートモジュールに記述し、F5 キーを押して実行してみてください。

Public Sub Chapter11_If()

    Dim numericalValue As Long
    numericalValue = 10
    Dim remainder As Long
    remainder = numericalValue Mod 2
    
    Debug.Print CStr(remainder = 0)
    
End Sub

 実行結果としてイミディエイトウインドウに以下のように出力されます。

True

 コードを説明します。まず、Long 型変数として numericalValue を宣言しています。numerical とは「数値の」という意味で、value は「値」を意味していますので、この変数は数値を保持する変数であることが分かります。それは変数の型が Long となっていることからも判断出来ますね。そしてこの変数 numericalValue に整数 10 を代入しています。

 次に、Long 型変数 remainder を宣言しています。remainder とは「余り」を意味しており、いわゆる割り算の「余り」のことです。この名前によってこの変数が割り算の余りを保持する変数だということが分かります。余りですから、当然整数です。そのため Long 型で宣言しているのですね。

remainder = numericalValue Mod 2

 この式は既に学習した内容です。Mod は余りを演算するオペレーターでした。numericalValue には既に 10 が代入されていますので、この式は 10 を 2 で割った時の余りを変数 remainder に代入することを意味しています。

 そして最後に Debug.Print CStr(remainder = 0) としています。CStr() はすでに何度も使用していますね。引数の値をテキスト型へ変換するメソッドです。では引数の remainder = 0 は何でしょうか?

 この式 remainder = 0 は、比較演算です。つまり、remainder の保持する値が 0 ならば True を、0 でないならば False と評価されます。このように演算結果が論理型の値として評価される式を条件式と呼びます。この例では 10 を 2 で割り算したときの余りが remainder に保持されていますので remainder は 0 ですね。つまり、remainder = 0 は True と評価され、CStr( True ) によってテキスト “True” へと変換されてイミディエイトウインドウには True が表示されます。

 さて、条件分岐における条件式について学習しました。以下のことをまず覚えておきましょう。

論理型の値として評価される式を条件式と言います。

 今まで学習してきた中で、「論理型の値と評価される式」にはどういったものがありますか?少し考えてみましょう。

 論理型の値として評価される式とは、今まで学習した様々な演算の中で、論理型の値として評価される演算がいくつかありましたね。比較演算と論理演算です。そしてもう一つ忘れてはならないのは、論理型変数です。変数はそれ単体であっても式なのです。ですから、論理型変数、比較演算式、論理演算式の3つが条件式に成り得るということです。(他にも条件式となる式がありますが現時点では未学習なので触れません)

比較演算子 = と代入演算子 =

 ここで一つ補足をしておきます。= は比較演算を行うオペレーターとしての機能の他に代入演算子としての機能も持っています。コードの中に登場する = が、比較オペレーターなのか代入オペレーターなのかを見分ける方法があります。

 代入オペレーターである = は、原則として文の最初に「左辺 = 右辺」という形で登場します。文の最初にこの形で記述されていれば、それは代入を意味しています。例外は一つだけです。For の直後に 左辺 = 右辺 と記述されているものも代入を意味しています。代入オペレーターとして機能するのはこの 2種類だけです。

 一方、比較オペレーターである = は、文の途中で登場します。ここで言う途中とは、メソッドの引数や制御文の中、計算式の中などのことで、簡単に言えば、先にあげた文の最初または For の直後に登場しない全てのケースでは比較オペレーターとして機能します。

条件分岐( If Then Else)

 条件分岐の最も基本的な形であり、使用頻度が最も高い書き方をまずご紹介します。先ほどのマクロを以下のように修正して、F5 キーで実行してください。

Public Sub Chapter11_If()

    Dim numericalValue As Long
    numericalValue = 0
    Dim remainder As Long
    remainder = numericalValue Mod 2
    
    If remainder = 0 Then Debug.Print "偶数"
    
    remainder = 3 Mod 2
    If remainder = 0 Then Debug.Print "偶数" Else Debug.Print "奇数"
    
End Sub
偶数
奇数

 実行結果は上記の通りです。

最もシンプルな条件分岐

7行目までは先ほどと同じですので、8行目を解説します。

If remainder = 0 Then Debug.Print “偶数”

 これが条件分岐の最もシンプルな基本形で If 文と呼ばれています。ぜひ記述の仕方を何度も練習してください。書き方は以下の通りです。

If 条件式 Then 条件を満たしたときに実行するコード

 If のすぐ後に「条件式」を記述し、Then の後に「条件を満たした時に実行するコード」を一つだけ記述します。条件式は既に述べました。論理型の値に評価される式でしたね。つまり条件式は必ず True または False として評価されます。そしてその条件式が True と評価されたとき、Then 以降のコードが実行され、条件式が False であったときは Then 以降のコードを実行せずに次の行へと進みます。このコードが実行される過程を観察してみましょう。

If remainder = 0 Then Debug.Print "偶数"   ←最初のコード
If True Then Debug.Print "偶数"        ←条件式が評価されます
Debug.Print "偶数"              ←条件を満たしたので Then 以降が実行されます

最もシンプルな条件分岐その2

 次に10行目と11行目のコードを説明します。まず10行目は 3 を 2 で割った時の余りを変数 remainder に代入しています。余りは 1 なので remainder には 1 が代入されるということになります。そして11行目が条件分岐となります。

If reaminder = 0 Then Debug.Print “偶数” Else Debug.Print “奇数”

 こちらも If 文ですが、先ほど紹介した If Then とは違い、If Then Else という形をしています。先に紹介した If Then と異なるのは、条件式を満たさなかったときに実行するコードを一つだけ指定することが出来る点です。書き方は以下の通りです。

If 条件式 Then 条件を満たしたときに実行するコード Else 条件を満たさなかったときに実行するコード

 If のすぐ後に「条件式」を記述し、Then の後に「条件を満たした時に実行するコード」を記述、さらに Else の後に「条件を満たさなかった時に実行するコード」を記述します。つまり条件式が True と評価されたとき、Then 以降のコードが実行され、条件式が False であったときは Else 以降のコードが実行されます。このコードが実行される過程を観察してみましょう。

If remainder = 0 Then Debug.Print "偶数" Else Debug.Print "奇数"最初のコード
If False Then Debug.Print "偶数" Else Debug.Print "奇数"
↑まず条件式が評価されます
Debug.Print "奇数"
↑条件式が False と評価されたので Else 以降の式が実行されます 

最もシンプルな条件分岐 まとめ

 最もシンプルな条件分岐を学習しました。この形は短い1行で記述するため読みやすさの点で優れています。そのため最も使用頻度の高い条件分岐の形と言えます。

条件分岐( If Then Else End If

 次に、以下のマクロを Sheet1 シートモジュールに記述し、F5 キーを押して実行してみてください。

Public Sub Chapter11_If_EndIf()

    Dim numericalValue As Long
    numericalValue = 10
    Dim remainder As Long
    
    remainder = numericalValue Mod 2
    If remainder = 0 Then
        Debug.Print "偶数"
        Debug.Print "numericalValue = " & CStr(numericalValue)
        Debug.Print "numericalValue / 2 = "; CStr(numericalValue / 2)
    Else
        Debug.Print "奇数"
        Debug.Print "numericalValue = " & CStr(numericalValue)
        Debug.Print "numericalValue / 2 = " & CStr(numericalValue / 2)
    End If
    
End Sub
偶数
numericalValue = 10
numericalValue / 2 = 5

実行結果は上記の通りです。

この形の If 文は、Then や Else のあとに複数の文を実行する必要がある場合に使用します。

 先ほど紹介した 1行 If 文は、Then 及び Else のあとに実行する文は一つだけでしたが、作成したい条件分岐は必ずそうとは限りません。今回のように分岐後に複数の文を実行させたいこともしばしばあります。そのような時は、この形の If 文を記述します。この形は、Then のあとに複数の文を記述することが可能で、同様に Else のあとにも複数の文を記述することが出来るのです。

 この制御構造は、If から始まり End If で閉じるという構造をしていることから、If ブロックと呼ばれることもあります。If から End If までを一つの構文ブロックとして考える訳です。初心者の方はこのようなブロックごとにコードを理解していく方が理解が容易かもしれません。

 次の上記コードの 4行目を、numericalValue = 10 から numericalValue = 5 に修正してから F5 キーで実行してみましょう。

奇数
numericalValue = 5
numericalValue / 2 = 2.5

 実行結果は上記に様に変わります。やっていることはとてもシンプルなので、異なる結果が表示されてしまった場合はコードをじっくり読みながら修正して下さい。

条件分岐( If Then ElseIf Then Else End If)

 次に、以下のマクロを Sheet1 シートモジュールに記述し、F5 キーを押して実行してみてください。

Public Sub Chapter11_If_ElseIf()
    
    Dim result As Long
    result = Conversion.Fix(Application.InputBox("テストの点数を入力してください。( 0 点から 100 点)", "テスト結果", Type:=1))
    If 80 <= result Then
        Debug.Print "評価:優"
    ElseIf 70 <= result Then
        Debug.Print "評価:良"
    ElseIf 60 <= result Then
        Debug.Print "評価:可"
    Else
        Debug.Print "評価:不可"
    End If
        
End Sub

実行すると「テストの点数を入力してください。( 0 点から 100 点)」というダイアログが表示されます。入力欄に 0 から 100 の間の任意の数値を入れると、イミディエイトウインドウに以下のように出力されます。(65 を入力した時の例)

評価:可

 それではコードを解説していきます。

    Dim result As Long
    result = Conversion.Fix(Application.InputBox("テストの点数を入力してください。( 0 点から 100 点)", "テスト結果", Type:=1))

3行目に Long 型変数 result を宣言し、4行目でその変数に何かを代入していますね。この代入式の右辺が長いので分解して順番に見ていきます。

Application.InputBox(“テストの点数を入力してください。( 0 点から 100 点)”, “テスト結果”, Type:=1)

これは Chapter 5 で一度説明していますね。Application は現在操作している Excel を表しており、そのメソッドである InputBox を使用しているコードです。InputBox メソッドを使用する際、引数として以下の3つの情報を渡しています。

①入力を求めるテキスト(プロンプト):テストの点数を入力してください。( 0 点から 100 点)

②ダイアログのタイトル:テスト結果

③戻り値のタイプ:1

Application.InputBox(①, ②, ③)

①②③の情報を InputBox メソッドにこのような順番で渡しています。すると以下のようなダイアログが表示されます。

渡した情報がダイアログのどこに表示されているのか確認してください。このメソッドは使い勝手が良いこともあり、ユーザーから何か情報を得たいときには便利です。

③はダイアログに表示される情報ではなく、ユーザーが入力出来るデータのタイプを指定しています。今回は 1 を渡しているのでユーザーが入力出来るのは数値だけとなります。(文字を入力して OK ボタンを押すとエラーになります)

今回は 65 と入力して OK ボタンを押してください。すると Application.InputBox は 65 という数値を返してきます。これにより

Application.InputBox(“テストの点数を入力してください。( 0 点から 100 点)”, “テスト結果”, Type:=1)

という式は

65

と評価されます。

よって、次に実行されるコードは以下のように変化します。

result = Conversion.Fix(65)

Conversion.Fix(65) は、Conversion クラスの Fix メソッドの呼び出しです。引数として 65 という数値を与えています。本来、この Fix メソッドは引数で受け取った実数に対して小数点以下を切り捨てた整数を返します。今回は 65 という整数を与えているので、そのまま 65 という整数を返してきます。

result = 65

よって上記の式へと変化します。この式が何をあらわしているかはもうお分かりですね。変数 result に 65 を代入します。

なぜ Conversion.Fix() を使っているのか疑問に感じた方もいるかもしれません。

result = Application.InputBox("テストの点数を入力してください。( 0 点から 100 点)", "テスト結果", Type:=1)

これでは駄目なのでしょうか?

 答えはそれでは駄目なのです。上記コードの場合、InputBox メソッドが返す値を直接に変数 result へ代入します。また、InputBox に指定した Type:=1 はユーザーに対して数値の入力を強制することは出来ますが、整数の入力を拒否することは出来ません。仮にユーザーが 69.8 と入力した場合どのような結果になるでしょうか。

result = 69.8

 ユーザーからの入力を InputBox は素直に返してきますので InputBox の処理が終了すると上記のコードが実行されます。result は Long 型変数なので整数しか扱うことが出来ません。そのため、69.8 という実数を result へ代入する際に暗黙の型変換が行われ、小数点以下が丸められてしまいます。問題はこの丸め方です。厳密には四捨五入とは異なりますが四捨五入に近い変換が行われたのち、result へ代入されます。そうすると、69.8 という点数が result に代入されると 70 になってしまいますね。点数が 70 点以上だと成績も「良」となってしまいます。69.8 ならば「可」と評価されなければいけません。こういった処理はいわゆるバグと言われるものです。このようなバグを防ぐために Conversion.Fix を用いて小数点以下を切り捨て、result へ代入しています。

(Chapter 6 で整数型変数へ実数を代入したとき「丸め」について解説しています)

次のコードの解説に移りましょう。

    If 80 <= result Then
        Debug.Print "評価:優"
    ElseIf 70 <= result Then
        Debug.Print "評価:良"
    ElseIf 60 <= result Then
        Debug.Print "評価:可"
    Else
        Debug.Print "評価:不可"
    End If

次は入力されたテストの点数を評価するブロックとなります。こちらもブロック構文となり、If から始まって End If で終わります。

先ほどの例と異なるのは、EllseIf があるという点だけです。以下が記述方法となります。

If 条件式1 Then
 条件式を満たした時に実行される文
ElseIf 条件式2 Then
 条件式1 を満たさず条件式2 を満たした時に実行される文
ElseIf 条件式n Then
 条件式1、条件式2 を満たさず条件式n を満たした時に実行される文
Else 
 どの条件式も満たさなかった時に実行される文
End If

Then の次行に、直前の条件式を満たした時に実行される文を記述します。ここには複数行に亘って実行文を記述することも可能です。

注意点は、いずれかの条件を満たし、Then のあとの文が実行されると他の条件式はすべて無視して End If まで飛ぶという点です。

それでは、65 を入力した場合に実行されるコードを追っていきましょう。

If 80 <= result Then

最初にこの条件式 80 <= result が評価されます。result は 65 ですから 80 <= 65 は False と評価されます。そのため Then に続く文は実行されず、次の ElseIf へと飛びます。

ElseIf 70<= result Then

この条件式 70<= result は 70 <= 65 となり、これも False と評価されます。よって Then に続く文はスキップして次の ElseIf へ飛びます。

ElseIf 60<= 65 Then

この条件式 60<=result は 60 <= 65 となるので True と評価されました。条件を満たしたということですね。そのため Then に続く文が実行されます。

Debug.Print “評価:可”

この文が実行され、イミディエイトウインドウには 評価:可 というテキストが表示されることになります。

このマクロを何度か実行し、任意の数値(小数でも構いません)を入力して動作を確認してみてください。

まとめ

 本稿では、条件分岐の代表的な構文である If 文について学習しました。1行で表現する If 文や、ブロック構文としての If 文を学習したことで、状況に応じてどちらの構文を使うべきかを選択出来ます。初めのうちはブロック構文の方が理解しやすいかもしれませんが、コードの読み書きに慣れるに従って 1行構文の方が断然読みやすくなります。初心者のうちから 1行構文に慣れ親しんでおいた方が上達の阻害要因は減りますから、1行構文で表現可能な条件分岐であるときはなるべく 1行構文を使うように意識することをお勧めします。

それでは本稿はここで終了です、お疲れさまでした。また次回お会いしましょう。

タイトルとURLをコピーしました