Visual Basic 初級講座 [改訂版] |
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
Visual Basic 中学校 > 初級講座[改訂版] >
2020/4/25
この記事が対象とする製品・バージョン
![]() |
Visual Basic 2019 | ◎ | 対象です。 |
![]() |
Visual Basic 2017 | ◎ | 対象です。 |
![]() |
Visual Basic 2015 | ◎ | 対象です。 |
![]() |
Visual Basic 2013 | ◎ | 対象です。 |
![]() |
Visual Basic 2012 | ◎ | 対象です。 |
![]() |
Visual Basic 2010 | ◎ | 対象です。 |
![]() |
Visual Basic 2008 | ◎ | 対象です。 |
![]() |
Visual Basic 2005 | ◎ | 対象です。 |
![]() |
Visual Basic.NET 2003 | △ | 対象外ですがほとんどの説明があてはまるので参考になります。 |
![]() |
Visual Basic.NET (2002) | △ | 対象外ですがほとんどの説明があてはまるので参考になります。 |
![]() |
Visual Basic 6.0 | × | 対象外です。 |
目次
プログラムは数千行、数万行に及ぶことが珍しくありません。
何行記述してもコンピューターは黙々と順番に実行していきます。この実行する順番のことを「フロー」と呼びます。フローとは流れという意味です。
通常のフローは上から下に流れていきます。
ボタンクリックなどのイベントが発生するとイベントハンドラー(たとえば、Button1_Click)が記述されているところに実行がジャンプするなど、上から下に流れない場合もあります。
VBなどほとんどのプログラミング言語にはフローを制御する構文が用意されており、指定した位置にジャンプしたり、条件によってある処理を実行したりしなかったりするフローや、繰り返し実行するフローなどを記述することができます。
フロー制御を実現する主な機能には下記があります。
1.条件判断構造
キーワードは If や Select Case です。
特定の条件の時に処理を実行したりしなかったり、条件によって処理を分岐させたりします。今回はこれの If を説明します。
2.ループ構造
キーワードは For や For Each、Do、Whileです。
処理を繰り返す構造です。回数で指定したり、条件で指定したり、対応する物の数だけ繰り返すなどの機能があります。
3.GoTo
キーワードは GoTo です。
指定した位置にジャンプします。これ以降、そのから下に向かってプログラムが実行されていきます。
|
条件制御構造の基本は If (読み方:If = イフ)です。If による制御構造は慣例的に「文」をつけて If文(イフぶん)と呼ばれます。
Windowsフォームアプリケーションで簡単なクイズゲームを作成してIfを試してみましょう。
プロジェクト名をQuizIf として、フォームにLabelとTextBoxとButtonを1つずつ配置し、プロパティを次のようにしてください。
コントロール | プロパティ | 値 |
---|---|---|
フォーム | Text | クイズ |
Label | Text | 元禄16年に出版された「曽根崎心中」の作者は誰でしょう? |
Font | Meiryo UI サイズ 24 | |
TextBox | (Name) | txtAnswer |
Font | Meiryo UI サイズ 24 | |
Button | (Name) | btnAnswer |
Text | 回答する | |
Font | Meiryo UI サイズ 24 |
コントロールの配置を整えて少し見やすくしましょう。私は次のようにしました。
このクイズの答えは近松門左衛門(ちかまつもんざえもん)です。
このアプリケーションで、btnAnswerボタンのクリックイベントにいろいろなIf文を書いて実行して動きを調べてみましょう。
最初は最も基本的な If文 です。
「近松門左衛門」と入力されたら「正解」と表示しましょう。
Private Sub btnAnswer_Click(sender
As Object, e
As EventArgs)
Handles btnAnswer.Click If txtAnswer.Text = "近松門左衛門" Then MsgBox("正解") End If End Sub |
簡単ですね。
MsgBoxはIfの中にあるので条件に合致したい場合だけ実行されます。
条件は式で記述します。この例の場合は txtAnswer.Text = "近松門左衛門" が条件を表す式です。
この例では、MsgBoxを実行する処理を1行だけ記述していますが、実行する処理は何行でも記述することが可能です。お勧めはしませんが何百行、何千行書いてもよいです。
Else(読み方:エルス)を使うと、「そうではない場合」に実行する処理を記述できます。
答えが間違っている場合に「はずれ」と表示してみましょう。
If txtAnswer.Text =
"近松門左衛門"
Then MsgBox("正解") Else MsgBox("はずれ") End If |
ElseIf (読み方:ElseIf = エルスイフ) を使うと、複数の条件で処理をわけることもできるようになります。
たとえば、「近松門左衛門」と入力されたときは「正解」を表示し、「十返舎一九」(じっぺんしゃいっく)と入力された場合は「おしい。それは『東海道中膝栗毛』の作者です。」と表示してみましょう。
If txtAnswer.Text =
"近松門左衛門"
Then MsgBox("正解") ElseIf txtAnswer.text = "十返舎一九" Then MsgBox("おしい。それは『東海道中膝栗毛』の作者です。") Else MsgBox("はずれ") End If |
ElseIfを使うと分岐をいくつでも増やせます。
「回答する」クリックしたのに、何も入力されていない場合はメッセージを表示する機能も追加してみます。
If txtAnswer.Text =
"近松門左衛門"
Then MsgBox("正解") ElseIf txtAnswer.text = "十返舎一九" Then MsgBox("おしい。それは『東海道中膝栗毛』の作者です。") ElseIf Len(txtAnswer.text) = 0 Then MsgBox("何か入力してください。") Else MsgBox("はずれ") End If |
txtAnswerに何も入力されていない状態とは、txtAnswer.Textが0文字の状態です。これを判断すべき条件として Len(txtAnswer.Text) = 0 で記述しています。
クイズのプログラムの出番はこれで終わりです。今回のプログラムだと1問しかクイズがありません。2問目・3問目・・・と出していきたいですよね。 繰り返し処理など今後初級講座で登場する仕組みと組み合わせればそれも可能になります。それにクイズではなく、英単語の練習などにも応用できそうですね。私は中学時代、自作の英単語練習プログラムで英単語を勉強していました。高校時代には積分の練習問題を作るプログラムを作成しました。実際に役に立つプログラムを作ることでプログラムがますます楽しくなっていきました。 |
ElseIf を使って処理を分岐させると、複数の条件に合致する場合でも実行されるのはどれか1つの処理です。言葉では説明しにくいので実例で説明しましょう。次のプログラムを見てください。
If TextBox1.Text =
"Hello"
Then MsgBox("こんにちは!") ElseIf Len(TextBox1.Text) > 0 Then MsgBox("何か入力されています。") End If |
この例では、TextBox1にHelloと入力されていれば「こんにちは!」を表示します。そうではなく、TextBox1に入力されている文字数が0より大きい場合(つまり、何か入力されている場合)には、「何か入力されています。」と表示します。
Hello と入力した場合、この両方の条件を満たしていますが、両方のメッセージが表示されるわけではなく、「こんにちは!」だけが表示されます。どれか1つの条件に合致したらその処理を実行して他の処理は実行しないということです。
Ifにはこのほかに1行で書く書き方があります。たとえば、次のような書き方ができますが、使用しないことが多いです。
If TextBox1.Text = "A" Then MsgBox("Aですね!") Else MsgBox("Aではないんですね。") |
これがあまり使用されない理由は、どこまでがIfの条件の時に実行される処理なのかわかりにくくなるからです。
最初に説明した複数行で書くIf文は必ず最後に End If と書いてあり、If 文が終わりであることがわかるようになっています。1行で書くIf文にはEnd Ifがありません。1行で書くIf文と複数行で書くIf文の両方を使ってしまうと、プログラムをぱっと見たときに、Ifの範囲が誤認してしまう危険があります。そうならないように注意してプログラムを見るのは骨です。このようにぱっと見でプログラムの内容を把握しやすいかどうかは「プログラムの可読性」と呼ばれ、可読性が悪いプログラムは誤認によるバグを埋め込んでしまう可能性が高くなるので良くないとされています。
Ifの構文は以上で全部です。構文だけ見ればそれほど複雑ではないことがわかると思います。
複数行のIf文の構文をまとめてみます。
赤い部分は必ず記述する必要があります。その他の部分、たとえば、ElseIfやElseは必要があるときだけ記述します。
If 条件1 Then
条件1 が True の場合(つまり、条件に当てはまる場合)に実行する処理
ElseIf 条件2 Then
条件2が True の場合(つまり、条件に当てはまる場合)に実行する処理
Else
どの条件も False の場合(つまり、条件に当てはまらない場合)に実行する処理
End If
条件の後ろには Then (読み方:Then = ズェン) はつけることになっており、プログラマーがThenを省略してもVisual Studioが自動的にThenをつけてくれます。
Thenには特に機能はなく、単に 条件の終わりの目印 です。(そのため、目印がいらない場合は Then を書かなくても良いのですが、Visual Studioが勝手にThenをつけるので、実務上 Then がない If 文を見たことがないです。)
If文の構文はこれだけなので、複雑な条件を記述するには 条件を式で表す の書き方を知っておく必要があります。
条件を表す式は If 文以外にもいくつかの機能で使用できます。次回詳しく説明します。
IfのなかにIfを入れるという使い方もできます。
If Len(TextBox1.Text) = 0
Then MsgBox("答えを入力してください。") Else If TextBox1.Text = "徳川家康" Then MsgBox("正解です。") Else MsgBox("違います。") End If End If |
このプログラムではTextBox1に何か入力されている場合、またIfで判断して、それが徳川家康なら「正解です。」、そうでないなら「違います。」と表示します。
このように何かの構造の中に何かの構造を入れることを ネスト または 入れ子 と呼びます。
ネストしていくとどんどんプログラムが読みにくくなっていくので通常はお勧めしません。2段階くらいのネストは普通にでてきます。3段階くらいになると、ちょっと嫌な感じはしますが珍しくはありません。コードレビューワーにはネストを解消するようにコメントされるかもしれません。(その方法は、場合によりますが、もっとVBのことを知っている必要があります)
Ifの構文を覚えていない初心者のために、または、覚えてはいるけど入力する手間を省きたい人のために、Visual Studioはいくつかの支援機能を持っています。
1つはコードスニペットというもので、コードエディターを右クリックして [スニペット] - [ スニペットの挿入] - [コードパターン - If、For Each、Try Catch、Property、その他] - [条件とループ] から挿入したいIf文を選択できます。
Visual Studio のバージョンによっては表示はことなっているかもしれません。
Visual Studio 2019で試したところ挿入できるのは「If...Else...End If」、「If...ElseIf...Else...End If」、「If...End If」の3つありましたのでIfのパターンは網羅されています。
マウスを使わないで、Ifと入力した次にTABを2回入力するだけでも自動的にコードスニペットを挿入してくれます。これはすばやくて楽ですね。知らない人にはマッハで入力しているように見えなくもないので度肝を抜くこともできます。IfElseやIfElseIfにつづけて TAB 1回でもそれぞれ対応したパターンが挿入できます。
スニペットの挿入キー | 挿入されるスニペット |
---|---|
If に TAB2回 | If...End If パターン |
IfElse に TAB 1回 | If...Else...End If パターン |
IfElseIf に TAB 1回 | If...ElseIf...Else...End If パターン |
どのコマンドでどのようなスニペットが挿入されるかは、[ツール]メニューの[スニペットマネージャー]でわかります。ここに独自のスニペットを登録することもできます。
スニペットを使わない場合でも Then と End IfはVisual Studioが自動的に入力してくれるので自分で書く必要はありません。
下の動画では = 0 と入力した後に Enter 押しています。Enterを押すことで自動的に Then と End If が挿入されるのがわかります。
Ifなどでフローを構文で制御するようになると、プログラムのちょっとしたミスで実行されるはずの部分が実行されなかったり、実行してはいけないときに何かが実行されてしまったりとプログラムが意図通り動かないことがあります。
プログラムが意図通りに動かないことを「バグ」と呼び、バグの原因を探して修正する作業を「デバッグ」と呼びます。
昭和時代のデバッグはプログラムを眺めながらどこに間違いがあるのか一生懸命探したものですが、令和の現在ではVisual Studioの強力なデバッグ機能を使うことができます。
その中でステップ実行はプログラムのどこが実行されているのか簡単に確認する機能です。
今後複雑なフロー制御を行っていくときにステップ実行は強い武器になります。
ステップ実行とは、普段勝手にどんどん実行されていくプログラムの流れを一時停止して、命令を1つずつ実行していく実行の方法です。
実行を一時停止させるための簡単な方法はブレークポイントを設定することです。Visual Studioで停止させたい行の左側をクリックすると茶色の ● が表示されます。これがブレイクポイントです。
この画像では、btnAnswer_Clickの最初の行にブレークポイントを設定しました。そのため実行を開始してbtnAnswerをクリックした瞬間に、実行が停止し、画面は次のようになります。
黄色くなっている行は、次に実行される行を意味しています。この画像の状態ではIf文はまだ実行されていません。
一時停止状態では後で紹介する自動変数ウィンドウなどいろいろな機能を使って変数の内容を調べたり、プログラムの実行状況をいろいろ収集してトラブルを解決するための情報を取得できるのですが、今回はフローの流れにだけ注目しましょう。
Visual Studioの開発設定を「全般」にしている場合、F10キーを押すと、この黄色になっている行を実行し、次に実行する命令の行で停止します。この操作を「ステップオーバー」と呼びます。
開発設定「全般」とは全般的な開発者とはVisual Studioを始めて起動したときの開発設定で「全般」を選択した状態です。後で、この設定を変更するには[ツール]メニューの[設定のインポートとエクスポート]で設定をリセットします。リセットするとウィンドウレイアウトやツールバーなどインストール後に変更した設定は初期状態に戻ってしまいますが、作成したファイルやデータが消えることはありません。リセット後に改めて全般を選んでください。古いバージョンのVisual Studioでは「全般的な開発者」と表記されていたと思います。
どのキーを押せばステップオーバーできるのかわからない場合は、よいかわからない場合、[デバッグ]メニューの「ステップオーバー」の右側にキー名が表示されているので確認できます。
ツールバーで操作する場合はステップオーバーはこのアイコンです。
それでは1回ステップオーバーさせてみましょう。
黄色い行が移動してこのような状態になりました。
MsgBox("正解")の行が飛ばされたので、If文の条件はFalseであったことがわかります。
なお、txtAnswer.Textと書いてある場所のTextの上でマウスカーソルをホバーさせるとtxtAnswer.Textに入力されている内容を見ることもできます。
If文の条件がFalseだったので次はElseIfの評価が実行されます。もう一度 F10 などでステップオーバーすると、私の場合、次のElseIfにジャンプしました。
もう1度 F10 などでステップオーバーさせるとこうなりました。
このMsgBoxが実行されるようです。
このようにプログラムがどのように流れているか、ステップ実行を行うことで手に取るようにわかるのです。
一時停止モードを解除するには、プログラムの実行ボタンを押すか、F5キーを押します。
ブレークポイントを解除するにはブレークポイントをクリックするだけです。
ステップ実行した結果、思ったのと違うフローが実行されている場合、どこに間違いがあるのか調べるのに自動変数ウィンドウが役に立ちます。
|
一時停止中に[デバッグ]メニューの[ウィンドウ] - [自動変数]で表示できます。
このウィンドウには現在停止している場所と関係があるさまざまな情報が表示されます。慣れないうちは何を意味にしているのかはわからないかもしれません。
Visual Studio 2013以上であれば自動変数ウィンドウには、メソッドなどを実行した戻り値が表示されるため、Ifの条件の式の判断結果が想像と違った場合、どういう値が判断に使われたのか確認できます。これを見ればIf文が予想と違う動きをしたときの原因はだいたいわかります。
自動変数ウィンドウはステップ実行などデバッグ中に既に実行したメソッドなどの戻りを表示します。まだ実行していないメソッドなどの戻り値は表示しませんので、自動変数ウィンドウで確認したければステップ実行などしながら実際に確認したいメソッドの行を実行しましょう。
表示されている日本語が少しぎこちないのは英語版の直訳だからです。たとえば、上の画像の例だと英語版では「Microsoft.VisualBasic.Strings.Len returned」と表示され、その右側の4も合わせると「Microsoft.VisualBasic.Strings.Len returned 4」つまり、「Microsoft.VisualBasic.Strings.Len は 4 を返しました。」というきれいな文章になります。英語と日本語は語順が違うので、このレイアウトではきれいな日本語にすることが難しくこのような表示になっているのだと思います。
※ LenはStringsモジュールのメソッドであり、StringモジュールはMicrosoft.VisualBasic名前空間なので、自動変数ウィンドウは Microsoft.VisualBasic.Strings.Lenと表示しています。
Ifなどで分岐が増えていくとプログラムがどんどん複雑になっていきます。ソフトウェア工学ではプログラムの複雑さを客観的な数値で計測する手法が開発されています。
客観的な数値の1つにサイクロマティック複雑度、または循環複雑度と呼ばれる指標があり、Ifなどの分岐の複雑さがわかります。
Visual Studio2019の場合プロジェクトを右クリックして、[分析とコードのクリーンアップ] - [コードメトリックスの計算]をクリックするだけでこの値を確認できます。
Visual Studioのバージョンによってメニューの階層や表示が異なっているように思いますが「分析」や「コードメトリックス」がキーワードです。古いVisual Studioにはこの機能はありません。
次のような結果が表示されます。この結果には自動生成されたプログラムも含まれます。
この画像の例ではbtnAnswer_Clickのサイクロマティック複雑度は 4 です。全然大丈夫です。数字が高いほど複雑です。25を超えると良くないというのがMicrosoftの評価です。
参考:CA1502: メソッドの実装を複雑にしすぎないでください
https://docs.microsoft.com/ja-jp/visualstudio/code-quality/ca1502-avoid-excessive-complexity
どのくらい複雑になると問題があるでしょうか。プロシージャ単位ではおおむね以下の表に示すような感覚です。
サイクロマティック複雑度 | 評価 |
---|---|
1 ~ 10 | よく構造化されている。テストしやすい。維持するのに手間がかからない。 |
10 ~ 20 | 複雑。テスト可能。維持するのに手間は必要。 |
20 ~ 40 | とても複雑。テスト困難。維持するのにとても手間をかける必要がある。 |
40以上 | テストは不可能。維持するのに途方もなく手間がかかる。 |
この表は下記サイトに記載されている表をもとにしていますが、このサイト独自の解釈ではなくだいたい一般的に認知されている評価です。
https://www.guru99.com/cyclomatic-complexity.html
40以上の評価は少し甘い気はします。「維持できない」「バグが混入するのを防げない」と評価する場合もあります。
もし、複雑なプログラムを書いてしまっていると思ったら、この値を確認してみてください。
サイクロマティック複雑度を低下させるもっとも簡単な方法はメソッド(プロシージャ)を小さな単位に分割することです。巨大なプロシージャはそれ自体が複雑です。プロシージャを分割する方法は今後初級講座で説明します。
なお、Visual Studioではサイクロマティック複雑度以外の指標も評価して総合点を「保守容易性指数」で示します。これは100が最も優秀で、0が最悪です。ここが緑色で表示されているうちは大丈夫というのがVisual Studioの判断なのですが、私はこの判断は少し甘すぎる気がしています。