ド素人でも学べる ExcelVBA 004 変数

ブログ

はじめに

 今回からプログラムの基本要素を見ていこう。最初は変数について学んで行く。
 簡単だが、引っ掛かりやすいポイントもあるから注意しよう。

 しっかりとサンプルコードを実行して試して見る事が大事だ。

変数

 変数はプログラムの中で値を入れる「箱」に例えられることが多い。
 わざわざ箱を用意して値を入れる必要があるのは、値が後から決まったり、途中で変更される事があるからだ。
 変数には、以下の3つの点に注目しよう。

  • 変数型 (箱のサイズや形)
  • 宣言の仕方 (これから使う箱を宣言しておく)
  • 変数の適用範囲 (変数が有効となる範囲)

変数型

 変数には「型」がある。いわば箱のサイズや形のようなものだ。
 変数型はいくつか種類があるが、VBAでは大きく分けると4つに分類できる。

 ・数値型 (Long型、Short型、Double型など)
 ・文字列型 (String型)
 ・日付型 (Date型)
 ・バリアント型 (Variant型)
 
 プログラミングでは、変数型は内部に入れる値に合ったものを選択するようにした方が良い。
 そうすればエラーを発見しやすくなるし、プログラミングの意図も判りやすくなる。
 
 ただ、VBAの仕様では必ずしも変数は宣言しなくても良い事になっている。
 宣言しない変数は、万能型のバリアント型を宣言したものとして扱われる。

数値型

 数値型は、その名の通り数値を入れる専用の変数型だ。違いは入れる事のできる数の大きさと、整数か小数を扱えるかの違いになる。
 Long型は、整数型なので小数は扱えない。(代入しても整数部分が切り取られる)
 (整数型には Int型というのがあるが、内部でLong型に変換しているようなので、今は使う意味があまりない。)
 Short型、Double型は、小数を扱えて、Double型の方が精度が良くなる。
 
 一見すると、小数も扱えて大きな値を扱える Double型のみで良いように感じるかもしれないが、使用するメモリーの量が異なる。 簡単に言うと必要以上に大きな箱を用意しても無意味だよねという事になる。
 変数は用途に応じたものを適切に選ぶ事が大事で、そうする事でプログラムが何をしようとしているかの意図が明確になる。

文字列型

 文字列型の変数はString型になる。半角英数字や全角もOKで、混在しても構わない。
 数値を文字列として代入する事もできる。
 ただ、変数から文字列として出力した数値は、セルに入れたりすると数値に自動変換される。
 この辺の挙動は、Excelのセルに手入力したときと同じだ。

日付型

 Excelでは、1900年1月1日を起点として、シリアル値セルの書式設定で日付を表現している。
 これを扱えるようにしたのが日付型になる。
 日付型は、0 や空白で値を初期化する事が出来ないのが大きな特徴だ。この事は扱う段階になったら解説する。

バリアント型

 バリアント型は、何でも入れられる型という風に考えて貰えれば良い。
 バリアント型は値が代入されてから型を決定するのが特徴で、初期状態では、nothing (何もない)という状態になっている。
 便利そうに見えるが、エラーが発生した際に原因を特定しずらいというデメリットもあるので、多用は禁物と言える。
 ただ、バリアント型でなければ処理できないケースもある。

 ここでは、値に適合する変数型を使うようにする。バリアント型でなければ処理できないケースは、そういう場面になったら解説する。

ブール型

 ブール型は、True(真) False(偽) の値しか取らない変数型だ。主な用途としては、If文などの分岐処理の条件式を満足するか否かを示す値として使ったり、フラグ用の変数として使ったりする。 

 後述する条件分岐の If文では、条件式が真(True) となった時に内部の処理を実行する事になる。
 (条件分岐については、後述するので今は分からなくても構わない。)

変数の宣言と使い方

 変数の宣言は以下のように書く。
 
  Dim i As Long
  Dim 変数名 As 変数型

 宣言する変数を使用する前に Dim を付け、変数名As変数型のように書く。
 宣言の位置は初めて利用する前ならどこでも良いので先頭にまとめて書かなくても構わない
 尚、VBAでは宣言せずにいきなり変数を使用する事もできるが、この場合、その変数はバリアント型として扱われる。
 
 実例を示すので、VBEに標準モジュールを追加して、記述して実行してみて欲しい。
 (実行はプロシージャ内にカーソルを置いて、F5キーだ。)

Sub test()
    Dim i As Long
    i = 10
    MsgBox i
End Sub

 1行目で i という変数を Long型(整数型) で宣言している。
 
 2行目で、i という変数に 10 を代入している。
 VBAでは、値を代入する時に = (イコール)を使う。
 
 また代入は、右辺から左辺にされる。
 つまりここでは、右辺の 10 を左辺の i に入れていることになる。


 
 最後の 3行目は、メッセージボックスで i の内容を表示させている。
 実行すると、メッセージボックスに 10 と表示されるはずだ。
 この場合の i は文字列ではなく変数として解釈されているわけだ。

 次は文字列型の変数を表示さてみよう。
 以下のようにプロシージャを書き変えてみて欲しい。

Sub test()
    Dim i As Long
    Dim str As String
    i = 10
    str = "こんにちは。"
    MsgBox str
End Sub

 ここでは、 i は値を代入しているだけで出力していないから無駄とも言える。ただ出力しないからと言ってエラーにはなっていない。
 さて、2行目で文字列型の変数 str を宣言している。
 4行目で str に文字列を代入している。”(ダブルクォーテーション)で囲む事を忘れないように。
 最後にメッセージボックスで str の内容をさせている。
 
 実行してみよう。結果は以下のようになるはずだ。

 次はバリアント型の変数を使ってみよう。
 以下のように書き換える。

Sub test()
    Dim i As Long
    Dim v
    i = 10
    v = "こんにちは。"
    MsgBox v
End Sub

 2行目の宣言部分では、As 変数型 の記述が省略されている。
 このようにバリアント型は、特別で、「変数型を省略した場合はバリアント型と見なす」というルールがある。
 もちろん、以下のように明示的に書いても間違いではない。

    Dim v As Variant

 4行目では、先程と同じように文字列を代入しているが、バリアント型変数 v は、この時点で文字列型に決定されることになる。
 最後にメッセージボックスで v の内容をさせている。
 
 バリアント型の特徴をもう少し観察してみよう。
 次のように書き換えてほしい。

Sub test()
    Dim i As Long
    Dim v
    i = 10
    v = "こんにちは。"
    v = i
    MsgBox v
End Sub

 5行目に追加してみた。
 4行目では、文字列を代入しているが、5行目で数値を代入している。
 5行目でバリアント型の v は数値型に変更される
 なのでメッセージボックスには、 10 と表示されることになる。
 このようにバリアント型の変数は、プログラムの途中から変数型を変更する事ができてしまう。

変数の適用範囲

 変数の適用される範囲は、スコープと呼ばれ、基本的にはプロシージャ内部という事になる。
2つのプロシージャがあって、同じ変数名を宣言して使っても、別のプロシージャでは赤の他人という事になる。

 プロシージャの境目を超えて使える、グローバル変数というものもあるが今は混乱するので、もう少しプログラミングに慣れてから覚えるようにしよう。

 ただ、初心者にも知っておいて欲しいのだが、プログラミングでは、変数はなるべく狭い範囲(ローカル)で使うのが好ましいという傾向がある。その方がバグが少なくなるしメンテナンスもしやすくなる。

 今は、別のプロシージャで同じ変数が出てきても別々の働きをすると覚えておいてほしい。

変数名に使ってはいけないワード

 変数名には使ってはいけないワードがある。
 ・先頭が数値ではいけない ( 1hensu などはダメ)
 ・VBAの予約語(sub,for,to,if など)は使えない
 ・<>?-~!”=\ などの記号は使えない ( アンダーバーは利用可能 abc_123 はOK。)

 
 日本語は変数名として使えますが、全角記号は避けるべきです。
 また、同じ適用範囲内(同じプロシージャ内など)で同じ変数名は使えません。
 Date などを変数名として使いたい時は、 myDate などとすれば予約語を回避できます。

数値計算

 数値変数の計算について見ていこう。
 数値計算は、通常の四則計算の他、商や余り、べき乗などが使える。
 詳しくは以下の記事を参照してほしい。
 ・演算子

演算子機能使用例結果
+足し算a = 3 + 25
引き算a = 3 – 21
*乗算a = 3 * 26
/除算a = 3 / 21.5
\a = 3 \ 21
Mod余りa= 3 Mod 21
^べき乗a = 3 ^ 29

 文字列の結合は説明したように & を使う。
 変数を使った計算と文字列の連結を組み合わせた例を示す。

Sub test()
    Dim i As Long, j As Long, k As Long, l As Long
    i = 10
    j = 3
    k = i \ j
    l = i Mod j
    MsgBox i & " ÷ " & j & " = " & k & " 余り " & l
End Sub

 実行すると、以下のように表示される。

 上記のように、変数の宣言を一行に書く場合は、カンマで区切って書く。2つ目以降は Dim を省略できる。
 プログラムでは、 i を j で割っている。k には商。l には余りが代入され、最後のメッセージボックスで式と答えを文字列として連結して表示させている。
 少々長いが、変数 & 文字列 & 変数 & 文字列,,,という風に連結されているのがわかると思う。
 このような記述の仕方は良く使うのでマスターしよう。

 マスターするためには、実際にプログラムコードを書いて実行してみることだ。

 以前話したように、5回ほど書いて実行してみれば、だいぶ慣れるはずだ。
 何も見ずに書けるように書けるようになればマスター出来た事になる。

間違えやすいポイント

 前のプログラムで、変数の宣言を一行に書いた。
 慣れてきたからと言って以下のように書かないようにしよう。

   Dim i, j, k, l As Long    'この書き方は間違い。どうしてかわかるかな?

 このように書いてしまう初心者は非常に多い。それでもエラー無く動いてしまうので、尚、始末が悪い。
 見る人が見れば、基礎が出来ていない事がバレバレだ。
 
 上のように宣言すると、l だけが Long型で他は、バリアント型として宣言した事になってしまう。
  i, j, k はそれぞれバリアント型でも、上記のプログラムではエラーにはならない。
 問題なのはプログラマー自身が、意図していないのに気付かない点だ。

 大きなプログラムになればなるほどエラーのリスクは高くなっていく、その分、変数型の管理はシビアになっていく。
 エラーの種となってしまうような書き方は避けるべきだ。

デバッグ プリント

 変数型の使い方を学習したので、プログラム進行中の変数の中身を見る デバッグ プリント について解説しておこう。
 デバッグ プリントは、メッセージボックスのように変数の値などをイミディエイトウィンドウに文字列で出力してくれるメソッド(命令)だ。
 以下のような書式で書く。

   Debug.Print  "文字列"

 メッセージボックスと似ているが、出力先がイミディエイトウィンドウになる点が異なる。
 上記のプログラムを書き変えて以下のように変更して実行してみよう。

Sub testDebugPrint()
    Dim i As Long, j As Long, k As Long, l As Long
    i = 10
    j = 3
    k = i \ j
    l = i Mod j
    Debug.Print i & " ÷ " & j & " = " & k & " 余り " & l
End Sub

 実行すると、今度はイミディエイトウィンドウに値を表示して、すぐに終了する。

 Debug.print はデバッグ用のメソッドとなる。デバッグとは不具合を解消するための作業の事だ。
 なのでプログラムの進行を妨げずに、その時点の値をイミディエイトウィンドウに表示して次に進む。
 
 メッセージボックスでも似たような意図で使うこともできるが、メッセージボックスはプログラムの途中でユーザーに何かを知らせるのが目的だ。
 
 これからVBAプログラミングを行っていく上でデバッグ プリントは日常的によく使う事になる。今後は、デバッグ プリントを使って説明していく事にする。

 Debug.print はVBAをやっている人ならスラスラ打ち込める。そのくらいよく使うコマンドだ。

まとめ

 今回は変数を中心に解説してきた。
 要は変数名を付けて型を設定すれば良いのだが、細かいルールがいくつかある。
 ・変数名は先頭に数値で始めたり、記号は使えない。VBAの予約語もダメ
 ・型を省略するとバリアント型になる
 ・使用する前に宣言する

 
 また、「間違えやすいポイント」に出てきたような宣言の仕方には気を付けてほしい。
 (この章を読んだ読者には、いい加減な変数定義をして欲しくない!)

 Debug.print に付いては今後頻繁に出てくるので、使っているうちに慣れてくると思う。

コメント

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