値が無い場合の表現

VBAでは値が入っていないときの表現がいくつもあります。

  • Empty
  • Nothing
  • Null
  • “”
  • vbNullString

これらの違いを説明します。


Empty

Emptyは、主に2つの場合で発生します。

1つは空白セルの値。もう1つはVariant型の変数の初期値になります。

VBAでは変数の定義時に型を指定せず暗黙の型変換とした場合はVariant型(なんでも型)になるためEmptyになります。セルや変数の値がEmptyかどうかを判定するにはIsEmpty関数を使いますが、””と比較してもちゃんと動作します。

以下のような感じで使います。

5行目ではA1セルに値をIsEmpty関数で判定していますが、6行目のようにIsEmpty関数を使わず、””と比較して書いてもちゃんと動作します。

ちゃんと動作する理由は、型指定をしなかったため暗黙でVariant型となった変数sが、=の右辺の””と比較する際に、””が文字列であることからEmptyをString型の””に変換した上で比較を行い、比較一致とみなしているためです。

上のコードのようにセルの値が入ってるかどうかを調べる場合は、IsEmpty関数よりも””と比較する方が直観的に分かりやすいため、私は6行目のように s = “” と書くことが多いです。


Nothing

Nothingはちょっとややこしいです。

NothingはObject型の変数の初期値です。Object型はFileSystemObjectクラスなどのクラス型の変数のことを指します。

いろんなサイトでも「Object型はオブジェクトを入れる」という、特に初心者にはなんとも分かりにくい説明をしてあるのですが、実際にObject型変数に入るのはクラスのインスタンスになります。

インスタンスとはクラスの実体になります。クラスが変数や型などの形だけを定義したものを指し、インスタンスがそれらの変数に実際に値を入れる領域を確保したものを指します。

でも、こんなことは知らなくても書き方さえ知ってれば使えます。

そのクラスがたくさんあるため総称して「オブジェクト」という言い方をしていますが、それが余計にわかりにくくしている気がします。

Object型の変数はかならずSetステートメントを利用して他のObject型の変数への参照を行う必要があります。

参照の際は通常、CreateObject関数を使います。

Nothingも参照時と同様にSetステートメントと一緒に利用する必要があり、別のObject型変数への参照を解放するために使います。

参照とは関数の引数をByRefで渡す場合の考え方と同じです。

このような書き方をします。ちょっと長いですが内容は簡単です。

9行目で参照したあとに、15行目でNothingを指定していますが、変数自体が使えなくなるわけではなく、どのObject変数も参照しなくなっただけの状態のため、21行目のように再度参照を行うと使えるようになります。

15行目でNothingを設定したあとに18行目のように使おうとしても「実行時エラー’91’ オブジェクト変数または With ブロック変数が設定されていません。」とエラーになります。なお、関数が終わる直前で Set obj = Nothing を入れていません。しかし無くても問題ありません。

Object型を使ったコードでは関数の最後に当たり前のように Set obj = Nothing の一文が入っているのですが、ほとんどの場合においてこれは意味がありません

なぜかというと、Object型の変数が解放されるのはNothingが代入されたときではなく、関数の処理が終わってObject型変数の役目が終わったときに解放されるためです。

また、27行目で参照先を解放後に、30行目を実行しても正しく動作します。

参照先の変数が解放されたにも関わらず動作するのは、Setステートメントで参照している実体が6行目のCreateObjectで残っているためです。

Object型変数がNothingかどうかを判定するには、以下のように書きます。

反対にNothingでないことを判定するには、以下のように書きます。



Null

NullはVariant型に設定される値ですが、Variant型の初期値はEmptyですのでNullは意図的に代入しなければ設定されません。Emptyは値がまだ設定されていない「未設定」状態を表し、Nullは値が「無い」ことを表します。

「未設定」と「無い」は意味が異なります。

Nullが発生する場面はあまりなく、高さが異なる複数行を選択した場合のRowHeightプロパティや同様に異なる幅の複数列でのColumnWidthプロパティを使ったときのように、対象値が異なる複数セルを参照したときにNullが返却されるぐらいです。

書式が異なる複数セルを参照した場合のNumberFormatプロパティなどもそうですね。

それ以外では、外部のDBを使うような場合でない限りNullが設定されることは無いんじゃないかなあ、という気がします。

Nullは上に書いた通り、明示的に、obj = Null のような書き方をしない限り入りませんし、そういう書き方をする必要もないため、Nullを使う場面はほとんどないと思います。

Nullかどうかの判定には、IsNull関数を使います。

IsNull関数とIsEmpty関数がごちゃごちゃになりそうですが、IsEmpty関数だけ使う、と思っていて大丈夫と思います。

少なくとも私はIsNull関数を使った記憶がほとんどありません。

上にあげたRowHeightプロパティやColumnWidthプロパティでもNullは発生しますが、そういう複数セルの参照ではループでセルを1つずつ処理した方がいいのでIsNull関数を使う場面はやはりあまり記憶にないです。


“”(空文字列)

“”はよく使われる値で、見たままの値です。String型です。””かどうかの判定もそのまま使います。

文字列変数の初期化によく使われますね。



vbNullString

vbNullStringはString型変数の初期値です。厳密には””とは違うのですが、””と同じと考えてもらっても問題ありません。実際、String型変数の初期値をウォッチ式で見ても、”” と表示されます。

vbNullStringは値を持っていないことを示しており、簡単に言えば代入されていない状態になります。代入されているかどうかを調べるにはStrPtr関数を使えば分かります。

上のコードの出力結果は以下になります。

なんでこんなものがあるのかというと、入力ダイアログなどの挙動に関係があります。「代入されていない」状態など持たずに初期値を””にしてしまえばいいのに、と思ってしまいそうですが、画面操作上そういう場面が発生することがあります。

入力ダイアログでテキストボックスに値を入れなかった場合は””、キャンセルボタンを押した場合は””ではなく代入していない、という状態になります。こういう外部の動作によるString型の戻り値が代入されているのかどうかが変わるため、vbNullStringは用意されています。

言い方を変えれば、こういう外部操作が関係なければ、””と同じとして考えて問題ありません。


まとめ

上の内容を整理しました。

種類 判定方法 判定例
Empty Variant IsEmpty関数 If (IsEmpty(s) = True) Then
Nothing Object Is Nothing If (obj Is Nothing) Then
Null Variant IsNull関数 If (IsNull(a) = True) Then
“” String 単純比較 If (s = “”) Then
vbNullString String StrPtr関数 If (StrPtr(s) = 0) Then