ExcelVBAの解説
VBAに限らず、すべてのプログラミング言語において変数はとても重要なものです。
変数は、値を記憶させておくためのものです。
はじめにお断りしておきます。VBAでは、変数は宣言しなくても使用できます。ですが、僕の独断で変数は宣言するものとして解説をします。 この点については、プログラマーの皆さんの考え方やコーディングの習慣、扱っている言語等によってご意見があると思いますが、ご了承ください。
宣言されていない変数は使用できないようにします。
「ツール」メニューの「オプション」をクリックします。
オプションダイアログボックスにて、「編集」タブの「変数の宣言を強制する」にチェックを入れます。
※画像では、「自動構文チェック」のチェックが外れていますが、初学者の方はチェックを入れておいた方がいいでしょう。
OKボタンを押して閉じます。この設定は、ずっと受け継がれますので、一度行っておけば今後必要ありません。
この設定をおこなっておくと、標準モジュールを新規に挿入したときに、コードが自動的に冒頭に追加されます。
Option Explicit の1文があると、宣言しないで変数を使用するとエラーになります。エラーというと「そんなもん出ない方がいい」と思われますが、修正すべき個所をいち早く教えてくれる機能と思えば、ありがたいのです。
※この設定をおこなう前に存在した標準モジュールには追加されません。既存の標準モジュールには、手入力してください。
何はともあれ、変数を宣言します。いよいよコードを書きますよ。
新規エクセルブックを開き、Visual Basic Edotor を開いたら、標準モジュールを用意してください方法はこちら。
以下のプロシージャを記述します。
Sub test1() Dim n As Integer n = 100 Range("B2").Value = n End Sub
Dim n As Integer が変数の宣言です。あえて日本語に訳すと、「整数型の変数nを宣言しますよ」となります。
構文は次の通りです。
Dim 変数名 As データ型
このプロシージャtest1 では、n が変数名、Integer がデータ型です。データ型については、もう少し後で説明しますよ。
変数名は、プログラマーが命名します。今回の変数名n は、僕が勝手に名付けさせていただきました。別にm でも、suuji でもかまいません。
ただし、変数名の命名にもルールがあります。このルールは、プロシージャの命名ルールと同じです。
変数は値を記憶させておくためのものですから、ただ宣言しただけでは、意味がありません。
変数に値を記憶させることを、「変数に値を代入する」と言います。
構文は次の通りです。
変数名 = 値
プロシージャ test1 では、n = 100 が値を代入しているコードです。
気を付けてほしいことがあります。 = の左辺と右辺を逆に書いてしまうと間違いです。
100 = n (これは間違いです)
この=は、「等しい」という意味ではなくて、「右辺を左辺に代入する」という意味の記号です。慣れるまでは特に注意が必要です。
まあ、そういうことです。
プロシージャ test1 では、Range("B2").Value = n が変数を使用しているコードです。
このコードを説明します。「セルB2に変数nの値を代入する」という意味です。代入するとセルB2に変数nの値が表示されます。
お気づきのとおり、このコードの = も、右辺を左辺に代入するという意味です。
さあ、ようやくといった感じですが、このプロシージャtest1を実行してみましょう。実行の方法はこちら
セルB2に 100 と入力されています。つまり、n は100を指していることが分かりますね。
データ型とは、データの種類のことです。いくつも種類があるのですが、まずは2つ覚えてください。
●整数型(Integer)例:0 , 20 , 356 , -100
●文字列型(String)例:a , hello , プログラミング , 20歳
なんとなく分かりますよね。20 は整数型ですが、20歳 は文字列型です。1文字でも文字が入ると文字列型です。
変数の宣言時にはデータ型を指定します。指定したデータ型の値しか変数に代入できません。
実験してみましょう。新たにプロシージャ test2 を作成します。
Sub test2() Dim n As Integer n = "20歳" Range("B3").Value = n End Sub
おっと、大事なことを言い忘れました。文字列は必ずダブルコーテーションで囲んでください。
test2 では、変数nに「20歳」という文字列を代入しています。しかし、変数nはデータ型として宣言されていることに注意してください。
さあ、どうなるでしょうか? さっそく実行してみましょう。
こんなエラーが出てしまいます。整数型の変数に文字列を代入したからです。「デバッグ」ボタンをクリックしてみましょう。
黄色い色のついた行でエラーが発生して処理が中断しているのです。
実行して、エラーが出たら、このように「デバッグ」ボタンをクリックして、どこでエラーが発生しているのかを確認する癖を付けましょう。
対処の方法を早く見つけることができるからです。
なお、現在はエラーのためにプログラムの実行が中断しているので、修正する前には「リセット」ボタンを押して、プログラムを終了してください。黄色い色が消えます。
それでは、変数nのデータ型を文字列型に修正しましょう。
Sub test2() Dim n As String n = "20歳" Range("B3").Value = n End Sub
今度はうまく動作するはずです。実行しましょう。
エラーが出ることなく、セルB3に 20歳 と表示されましたね。
変数を使うときは、どんな値を記憶させておきたいのか、データ型を意識するようにしましょう。
今まで2つのプロシージャ(test1 と test2)を作成しました。
2つのプロシージャを見ると、どちらも変数nを宣言して使用しています。しかも、片方は整数型で、もう片方は文字列型の変数として使用しています。
これは、許される行為です。複数のプロシージャで、同じ名前の変数を使うことは、問題ありません。
実は、変数には寿命があって、そのプロシージャ内でしか生きていられないのです。だから、同じ変数名であっても、それは別の変数とみなされるのです。
ただし、同じプロシージャ内で、同じ名前の変数を複数回宣言することはできません。たとえ、データ型を変えたとしても、です。
確認してみましょう。以下のプロシージャを作成します。変数nを2度宣言しています。
Sub test3() Dim n As Integer Dim n As String n = "こんにちは" Range("B4").Value = n End Sub
「デバッグ」メニューの「VBSProjectのコンパイル」をクリックします。これは、文法エラーをチェックする機能です。コードに問題がないと画面に変化は見られませんが、文法的なエラーがあると警告画面が表示されます。
以下の通り、警告メッセージが表示され、問題の箇所がハイライト表示されます。メッセージの内容は必ず読むようにしましょう。エラーの原因のヒントになるからです。
それでは、問題です。どちらかの変数宣言を削除すれば動作するのですが、どちらを削除したらいいのでしょうか?
そうですね。変数n に文字列を代入しているので、整数型で宣言している方を削除します。
さて、今さら、という感があるのですが、変数を宣言しないで使用してみます。いきなり n に100を代入しています。
Sub test4() n = 100 Range("B5").Value = n End Sub
「デバッグ」メニューの「VBSProjectのコンパイル」をクリックすると、エラー警告が出ますね。きちんと宣言しましょう。
プログラムを書いていると、こういうときが必ず出てくるのですよ。
例えば、変数res に値を格納するのは、プロシージャtest5 で、変数の値をセルに表示するプロシージャが test6 だとします。
プロシージャ test5 で変数宣言をすると、別のプロシージャではその変数を使うことができません。そのプロシージャの中でしか変数は有効ではないからです。
このように、複数のプロシージャで同じ変数を使いたいときは、プライベート変数を使います。
プライベート変数は、宣言する場所が決まっています。そのモジュールの最初のプロシージャよりも上のエリア(宣言セクションと呼びます)で宣言します。
構文は以下の通りです。
Private 変数名 As データ型
それでは、以下のコードを書いてみましょう。下の画像を参考にして、Private変数を書くときは、場所に注意してください。
Private res As Integer Sub test5() res = 120 End Sub Sub test6() Range("B7").Value = res End Sub
※プロシージャの順番は、自由に変更できます。今回のようにプロシージャ test1 の上に test5 や test6 を書いても問題ありません。Cut and Pasteで後から移動しても大丈夫です。
さて、プロシージャ test5 を実行するとエクセルに変化はあるでしょうか?
そうです。答えはノーです。
プライベート変数に値を代入しているだけですからね。
それでは、プロシージャ test5 を実行してください。
さらに、プロシージャ test6 を実行してください。
結果は次の通りです。test5 で代入した値がセルB7に表示されていますね。プライベート変数を使っているので、test6 の変数res の値は120になっているのです。
プライベート変数に代入された値は、標準モジュールの場合、エクセルを閉じるまで覚えているので、test6 を再度実行してもやはり、セルB7には120が表示されます。
もう一つ、問題です。プロシージャ test5 を実行しないで、プロシージャ test6 を実行するとどうなるでしょうか?
これを確認するためには、いったんエクセルを閉じなけばなりません。任意の名前で任意の場所にこのエクセルファイルを保存してください。
注意してほしいことがあります。ファイルの種類を「Excelマクロ有効ブック」にしてください。プログラムを書いたエクセルファイルは、これを選択することを覚えておいてください。
保存したら、このファイルを閉じてください。その後再度開いて、プロシージャ test6 を実行してください。
プライベート変数に値を代入していないと、0になることが分かります。
エラーにはならないで、0になるからといって、こういう使い方をしてはいけません。変数には値を代入してから使いましょう。
プロシージャの項で、プロシージャは、別のプロシージャから呼び出すことができますよ、と紹介しました。
6つもプロシージャを作ってきたので、ここで、一度に6つのプロシージャを実行してみましょう。
こんなコードを書けばいいのです。
Sub ExecuteAll() test1 test2 test3 test4 test5 test6 End Sub
プロシージャ名を書くと、そのプロシージャが呼び出されて実行されるのです。
プロシージャ ExecuteAll は、test1 から順番に test6 まで呼び出して実行しています。呼び出すだけのプロシージャです。こういうプロシージャは、ありです。
結果は以下の通りです。
さて、最後に面白い変数を紹介しましょう。
プロシージャの中で宣言された変数は、そのプロシージャの処理が終わるとなくなってしまうことは、すでに取り上げました。
そのプロシージャを再度実行すると、前回代入された値はきれいさっぱり忘れて、一から出直し(再び変数が宣言され、値が代入される)になります。
ちなみに、プロシージャの中で宣言された変数のことを、「ローカル変数」といいます。名前を紹介するのが今頃になってしまってすみません。
くどいようですが、ローカル変数は、プロシージャが終わるとなくなってしまう(消えてしまう)のです。
ところが、消えてなくならないローカル変数があるのです。それが「静的変数」です。
静的変数は、プロシージャの中で宣言しますが、 Dim を使いません。次のような構文になります。
Static 変数名 As データ型
なにはともあれ、プロシージャを書いてみましょう。
Sub test7() Static n As Integer n = n + 1 Range("B8").Value = n End Sub
静的変数nを宣言し、次の行で、n の値をインクリメント(1増やすこと)しています。インクリメントについては、書籍「子どもの”プログラミング的思考"をグングン伸ばす本」でも解説しましたね。前回の値に1を加算した値を変数に代入しなおしているのですね。
それでは実行してみましょう。セルB8 には 1 と表示されます。
再度実行すると、セルB8 には 2 と表示されます。前回実行されたときの値 1 を覚えているのです。
実行を続けると、1ずつ増えていくことが分かります。これが静的変数の特徴です。
ただし、静的変数は、宣言したプロシージャでのみ有効です。他のプロシージャからは見えませんので注意してください。
静的変数は、書籍「子どもの”プログラミング的思考"をグングン伸ばす本」の第8章 エクセルがひっくり返る? で使用していますよ。