変数には型という仕組みがあります。
変数は、何かを入れる入れ物のようなものですが、たとえばテニスラケット用のケースにゴルフのクラブは入りませんよね。あるいは、ギターのケースにトロンボーンは入りません。また、もし濡れた物を入れるなら、きっと水が漏れないビニール製の入れ物を使うでしょう。紙の袋では破れてしまうかもしれません。変数にもいろいろなタイプがあり、数値を入れる専用の型や、文字列を入れる専用の型などがあります。変数を宣言するときは、その変数に何を入れるかをあらかじめ想定して、適切な型を指定しなければなりません。
VBAでは、次のような型があります。よく使う型は太字にしてあります。
型名 | 型指定文字 | 格納できるデータ |
---|---|---|
ブール型 | Boolean | TrueまたはFalse |
バイト型 | Byte | 0~255までの整数 |
整数型 | Integer | -32,768~32,767の整数 |
長整数型 | Long | -2,147,483,648~2,147,483,647の整数 |
通貨型 | Currency | -922,337,203,685,477.5808 ~ 922,337,203,685,477.5807の固定小数点数 |
単精度浮動小数点数型 | Single | 負の値:約-3.4×10(38乗)~-1.4×10(-45乗)正の値:約1.4×10(-45乗)~1.8×10(38乗) |
倍精度浮動小数点数型 | Double | 負の値:約-1.8×10(308乗)~-4.0×10(-324乗)正の値:約4.9×10(-324乗)~1.8×10(308乗) |
日付型 | Date | 日付:西暦100年1月1日~西暦9999年12月31日時刻:0:00:00 ~ 23:59:59 |
文字列型 | String | 任意の長さの文字列 |
オブジェクト型 | Object | オブジェクト |
バリアント型 | Variant | すべてのデータ |
最もよく使われる型は、なんといっても長整数型(Long)と文字列型(String)でしょう。整数を格納する型は、長整数型(Long)のほかにInteger(整数型)もありますが、Integer(整数型)は最大で32,767までしか入りませんから、特別な事情がある場合を除いて、整数を入れる変数は長整数型(Long)で宣言すればいいでしょう。また、たとえば月を表す数値(1~12)のように、非常に小さい整数を格納する変数としてバイト型(Byte)を使っているケースをときおり見かけますが、これは相応しくありません。バイト型(Byte)は、バイナリデータという特別な値を格納するために用意された型です。もちろん、単純な数値を格納することも可能ですが、すごく変です。
と覚えておきましょう。ほとんどのマクロでは、これだけで十分です。
長整数型(Long)型は整数しか格納できない点に留意してください。小数点以下の数値は格納できません。次のマクロで確認してみましょう。
Sub Sample2() Dim tmp As Long tmp = 10 / 4 MsgBox tmp End Sub
10÷4は2.5です。しかし、変数tmpには2しか入っていません。このように、小数点以下の数値を扱う変数は単精度浮動小数点型(Single)を使います。
Sub Sample2() Dim tmp As Single tmp = 10 / 4 MsgBox tmp End Sub
ブール型(Boolean)は、TrueまたはFalseのいずれかを格納するときに使います。
Sub Sample3() Dim flag As Boolean If Range("A1") <> "" Then flag = True Else flag = False End If If flag Then MsgBox "セルA1は空ではありません" Else MsgBox "セルA1は空です" End If End Sub
日付型(Date)は、日付や時刻のデータを格納するときに使います。
Sub Sample4() Dim tmp As Date tmp = Now MsgBox Year(tmp) End Sub
セル自身やワークシート自身など、オブジェクトを格納するときはオブジェクト型(Object)を使います。
Sub Sample5() Dim ws As Object Set ws = ActiveSheet MsgBox ws.Name End Sub
Setの使い方は「Setを使うケース」で解説します。
どうです?面倒くさいですか?
もう20年以上前ですが、私が初めてプログラミング言語を学んだときも、この変数の型で悩みました。「いくつの整数を格納するかなんて、プログラムを実行してみなければわからない。そもそも、数値が入るか文字列が入るか事前にわからないときは、どーすりゃいいの?」みたいに。ですから、ビギナーの方が、この変数の型で悩む気持ちはよくわかります。ですが、ちょっと待ってください。上の表の一番下にバリアント型(Variant)というのがあります。格納できるデータには「すべてのデータ」とあります。そう、バリアント型(Variant)の変数は、何でも入れることができる万能の型なんです。整数だろうが、文字列だろうが、小数点以下の数値だろうが、配列だろうが、オブジェクトだろうが、もう何でも格納できちゃいます。
そんな便利な型があるのなら、何も面倒くさい型指定なんてする必要ないじゃん!
そう感じた方もきっといるでしょう。
そうです。その通りです。どの型を指定すればいいかわからないときはバリアント型(Variant)を指定すればいいのです。
「どの型を指定すればいいかわからない → だから変数は宣言しない」という発想が乱暴だと言ったのは、そういう意味です。「どの型を指定すればいいのかわからない → だったらバリアント型(Variant)を指定すればいい → そのかわり変数の宣言はする」と、そう考えれば楽でしょ。変数の宣言は、決して難しくありません。「Dim 変数名」と書けばいいのですから。
バリアント型(Variant)の変数を宣言するには、
Dim 変数名 As Variant
と書きます。あるいは、もっと簡単な方法があります。VBAでは、型の指定を省略すると、その変数はバリアント型(Variant)が指定されたものとみなす、というルールがあります。したがって、バリアント型(Variant)の変数は
Dim 変数名
だけでいいんです。これなら超簡単ですね。
変数の型がわからないのなら、無理して覚えなくていいです。型指定がネックになって変数の宣言を省略するくらいなら、全部の変数をバリアント型(Variant)にすればいいです。ただし、適切な型を指定できる方が、できないよりはいいでしょう。ですから、VBAの学習を続けて、余裕ができたら型についても学んでください。
何でも格納できる万能のバリアント型(Variant)は、しかし「あまり使うべきではない」とも言われています。その理由は、おおむね次の2点です。
バリアント型(Variant)変数は、その他の型に比べて実行速度が遅くなります。しかし、非常に高速なCPUやメモリを搭載した現在のパソコンでは、その差はごくわずかです。たとえば、次のマクロで確認してみましょう。
Declare Function GetTickCount Lib "kernel32" () As Long Sub Sample6() Dim i As Long, ST As Long ST = GetTickCount For i = 1 To 10000 Cells(i, 1) = i Next i MsgBox (GetTickCount - ST) / 1000 End Sub Sub Sample7() Dim i As Variant, ST As Long ST = GetTickCount For i = 1 To 10000 Cells(i, 1) = i Next i MsgBox (GetTickCount - ST) / 1000 End Sub
【Sample6の実行結果】
【Sample7の実行結果】
実行したパソコンは、Windows XP(Home)+Excel 2007+Atom+1GBメモリの、いわゆるネットブックです。
For Nextのループで使用するカウンタ変数iを、Sample6では長整数型(Long)で宣言し、Sample7ではバリアント型(Variant)にしました。10000回のループを実行して、その差はわずか0.078秒です。これって、重要な問題でしょうか?
誤動作の原因になるというのは、一例を挙げると次のようなケースです。
Sub Sample8() Dim A As Long, B As Long A = InputBox("数値1は?") B = InputBox("数値2は?") MsgBox A + B End Sub Sub Sample9() Dim A As Variant, B As Variant A = InputBox("数値1は?") B = InputBox("数値2は?") MsgBox A + B End Sub
【Sample8の実行例】
【Sample9の実行例】
InputBox関数は、マクロ実行中にユーザーからデータを受け取る命令です。InputBoxは、入力されたデータを文字列形式で返します。Sample8では、変数Aと変数Bがどちらも長整数型(Long)で宣言しています。文字列型で返された「100」と「200」は、自動的に型変換されて、整数として2つの変数に格納されます。変数Aと変数Bには整数が入っているのですから「A + B」で足し算が行われて「300」が表示されます。
一方のSample9は、変数Aと変数Bがバリアント型(Variant)で宣言されています。InputBoxは文字列型を返しますので、「100」と「200」はどちらも文字列として格納されます。文字列に対して「+演算子」を使うと、「&演算子」と同じように文字列同士が結合されます。したがって「100」と「200」が結合されて「100200」となりました。
変数の型指定によって実行結果が異なるのは事実ですが、誰もが、毎回、必ず遭遇する現象ではありません。たとえば、次のようなケースでは問題ありません。長整数型(Long)もバリアント型(Variant)も、同じ結果になります。てことは、バリアント型でもOKということです。
Sub Sample10() Dim A As String, B As String Dim C As Variant, D As Variant A = "100" B = "200" C = "100" D = "200" MsgBox A + B MsgBox C + D End Sub Sub Sample11() Dim A As Long, B As Long Dim C As Variant, D As Variant A = 100 B = 200 C = 100 D = 200 MsgBox A + B MsgBox C + D End Sub
【Sample10の実行結果】
【Sample11の実行結果】
本来なら型指定をすべき変数を、バリアント型(Variant)として扱うデメリットはほかにもあります。
確かに、次のようなコードを見ると、何となく落ち着きません。
Sub Sample12() Dim buf Dim i buf = InputBox("名前は?") For i = 1 To 5 Cells(i, 1) = buf Next i End Sub
InputBox関数は文字列を返しますので、それを受ける変数bufは文字列型が一般的です。For Nextステートメントで使うカウンタ変数は、長整数型(Long)が相応しいでしょう。できれば、次のように型指定されていた方が、何となくしっくりきます。
Sub Sample12() Dim buf As String Dim i As Long buf = InputBox("名前は?") For i = 1 To 5 Cells(i, 1) = buf Next i End Sub
バリアント型(Variant)変数を多用するということは、歯ブラシだろうがエンピツだろうが、何でもかんでもスーツケースに入れるようなものです。変数の型指定を理解している者からすると、違和感を感じるのも無理はありません。
理想は、適切な型を宣言できるようになることです。そのために学習することも必要です。ただし、変数の型を適切に使い分けられないビギナーのうちは、無理して苦労しなくていいです。バリアント型を使ってください。そして、余裕ができたら、変数の型についても学習してください。「型は覚えなくていい」というのは、そういう意味です。