【AccessVBA】 NullとEmptyとNothingと空の文字列の違い

AccessVBA開発

VBAでは変数やフィールドに有効な値がない状態や、空の状態を表す値がいくつもあります。
ここでは、それぞれの意味や使用上の注意についてご紹介します。

■長さ0の文字列(””)

文字を1つも含まない文字列 (“”) です。
「長さ0の文字列」の名前のとおり、Len関数やLenB関数の引数に指定すると0を返します。

    Dim myStr As String
    myStr = ""
    Debug.Print Len(myStr)     '--> 0 と表示される

■値0の文字列(vbNullString)

String型の変数の初期状態を表す値です。vbNullStringという定数で表します。
長さ0の文字列(””)と同様に、Len/LenB関数の引数に指定すると 0 を返します。
また、「If vbNullString = “” Then」のように比較すると、True になります。
そのため、空の文字列として長さ0の文字列 (“”)と区別されずに扱われることが多いですが、長さ0の文字列とは異なります。

値0の文字列と長さ0の文字列は、StrPtr関数で判別できます。
StrPtr関数はString型の変数のアドレス値を返す関数です。
StrPtr関数に 値0の文字列(vbNullString)を指定すると 0 を返します。
一方、長さ0の文字列(””)を指定すると、変数のアドレス値を返します。

■Empty

バリアント型の変数に格納される特殊な値(リテラル値)です。
Emptyは変数が初期化されていない状態を表します。バリアント型の変数の初期値です。
また、Emptyを格納できるのはバリアント型だけです。

バリアント型は、文字列や数値、日付やブール値など、いろいろなデータを扱うことができる特殊なデータ型です。Emptyのほか、Nullなどの特殊な値もバリアント型のリテラル値です。
Emptyかどうかは、次のようにIsEmpty関数で判定します。

    Dim myVar As Variant
    Debug.Print VarType(myVar)   '--> 0(定数vbEmpty)と表示される
    Debug.Print TypeName(myVar)  '--> Empty と表示される
    Debug.Print IsEmpty(myVar)   '--> True と表示される

VBAでは、明示的に型を変換しなくても、暗黙的に型の変換(型強制)が行われます。
バリアント型のEmptyを文字列として扱うと、String型に型強制されて長さ0の文字列(””)になり、数値として扱うと0に、ブール値として扱うとFalseになります。

    Dim myVar As Variant                    '初期値はEmpty
    If myVar = 0 Then Debug.Print "True"    '--> True と表示される
    If myVar = "" Then Debug.Print "True"   '--> True と表示される

ちなみに、Excelのセルを表すRangeオブジェクトのValueプロパティはバリアント型で、初期値はEmptyです。
セルが初期状態のとき、長さ0の文字列や数値の0と比較するとTrueになるのは、Emptyがこれらに型強制されているためです。

■Null

Nullは、バリアント型の変数に格納される特殊な値(リテラル値)です。
特殊な内部処理形式(vbNull)を持ち、有効なデータが格納されていないことを表します。
NullかどうかはIsNull関数で判定します。

    Dim myVar As Variant        '初期値はEmpty
    myVar = Null                'Nullを代入
    Debug.Print VarType(myVar)  '--> 1(定数vbNull)と表示される
    Debug.Print TypeName(myVar) '--> Null と表示される
    Debug.Print IsNull(myVar)   '--> True と表示される

Nullを格納できるのはバリアント型だけです。
ADOやDAOを使ってデータベースを扱う場合、フィールドを操作するオブジェクトのValueプロパティはバリアント型のため、値のない状態として Null を扱うことができます。

また、変数やフィールド、Accessフォーム/レポートのコントロールがNullになるのは、次のケースです。

  1.  明示的にNullを代入したとき
  2.  Nullを含む演算(計算)を行ったとき
  3.  フィールドやAccessフォーム/レポートコントロールに有効な値がないとき

このうち、2)については、値がないものと演算をするのですから、結果も有効な値にならないというわけです。
3)については、少し注意が必要で、フィールドを表すオブジェクトやコントロールのValueプロパティはバリアント型です。そしてバリアント型の初期値は前述のとおりEmptyです。しかし、フィールドに有効な値がない場合や、バインドしていない(非連結)コントロールの場合、初期値はEmptyでなくNullになっています。


●補足1●

Excelのユーザーフォームにもテキストボックスがありますが、Acccessのフォーム/レポートのテキストボックスとは異なります。
Excelのユーザーフォームで使用するテキストボックスの場合、Valueプロパティはバリアント型ですが、内部処理形式はString型で、値0の文字列(vbNullString)に初期化されています。

●補足2●

レコードセットを使用して処理を行う場合、元のフィールドが数値型でも値がなければNullになるため、それを使って演算すると結果はNullになってしまいます。
値がないときには別の値に置き換えたいという場合は、演算前にNullかどうかを判定するか、またはNz関数を使用して別の値に置き換えてもよいでしょう。
ただし、「If myVar = Null」や「If myVar <> Null」のように比較するといずれもFalseになってしまうので、Nullの判定にはIsNull関数を使用してください。

■Nothing

オブジェクト変数に格納される特殊な値(リテラル値)です。
オブジェクト変数が特定のオブジェクトと関係付けられていないことを表します。
オブジェクト変数を宣言した後、オブジェクトへの参照が設定されるまで、オブジェクト変数にはNothingが設定されています。
また、オブジェクト変数が特定のオブジェクトを参照しているとき、Setステートメントを使用して次のように記述すると、オブジェクト変数と参照先のオブジェクトとの関係が無効になります。

    Set myObj = Nothing

ただし、オブジェクト変数にNothingを代入しても、オブジェクトを破棄しているわけではないことに注意。
オブジェクトは、どこからも参照されなくなったときに、自分自身を破棄する仕組みになっています。そのため、複数のオブジェクト変数が同じオブジェクトを参照している場合は、すべての変数に明示的にキーワードNothingを設定するか、または参照しているすべてのオブジェクト変数の適用範囲 (スコープ) 外になるまで、リソースは解放されません。

オブジェクト変数がNothingであるかどうかを確認するには、Is演算子を使用します。

    If myObj Is Nothing Then
        Set myObj = Forms![フォーム1]
    End If

この例では、オブジェクト変数Objが特定のオブジェクトと関連付けられていない場合は、Objにフォーム1を割り当てています。

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