2009年5月14日木曜日

VBA のバリアント型

配列の走査

VBA で文字列の配列の初期化」のついでに配列の走査。変数 strAry が文字列の配列だとすると、

    Dim idx As Integer
    For idx = LBound(strAry) To UBound(strAry)
        Debug.Print strAry(idx)
    Next

LBound, UBound 関数が記憶の彼方にあって全く思い出せなかった。 (o_ _)o~†

 

For Each … Next

For Each を使う場合は、

    For Each elem In strAry
        Debug.Print elem
    Next

もし、上記に先立ち、

    Dim elem As String

と宣言すると、

090513-005

For Each の場合、要素を指す変数はバリアント型でないといけなかったかぁ。。 (@_@;)

ヘルプ > Microsoft Visual Basic Documentation > Visual Basic プログラミングのヒント の「For Each...Next ステートメントの使い方」によると、

For Each...Next ステートメントは、コレクションの各オブジェクトまたは配列の各要素に対して、一連のステートメント ブロックを繰り返し実行します。

また、「For Each...Next ステートメント」 には、要素が代入される変数について、

コレクションや配列の各要素を繰り返す変数を指定します。コレクションの場合、引数 element にはバリアント型 (Variant) 変数、総称オブジェクト型変数、または任意の固有オブジェクト型のオブジェクトの変数を指定できます。また、配列の場合は、引数 element にはバリアント型のみ指定できます。

 

クラスモジュール

For Each … Next と言えば、オブジェクトのコレクションを走査するときによく使った。例えば、プロパティに「名前」を持つ Person クラスを定義し、

Dim mstrName As String

Public Property Let Name(strName As String)
    mstrName = strName
End Property

Public Property Get Name() As String
    Name = mstrName
End Property

このクラスのオブジェクトをコレクションに追加し、For Each … Next で走査するには、

    Dim col As New Collection
    
    Dim p1 As New person
    p1.Name = "Tarou"
    Dim p2 As New person
    p2.Name = "Jirou"
    
    col.Add p1
    col.Add p2
    
    Dim person As person
    For Each person In col
        Debug.Print person.Name
    Next

 

バリアント型

ところで、バリアント型はあまり使ってなかったので、For Each で使えることを知らなかった。上記でも For Each で使っている要素を代入する変数 person の型宣言をせずにバリアント型としても使用できる。

ヘルプの「バリアント型 (Variant)」を見ると、

バリアント型は特殊なデータ型で、固定長の文字列型 (String) データとユーザー定義型を除く、あらゆる種類のデータを格納することができます。

(太字は引用者による)

バリアント型というと、文脈に応じて適用する演算子の意味が変化し、メモリを結構使うということしか頭に残っていない。 ^^;

バリアント型には、特殊な値 Empty 値Null 値、およびエラー値や Nothing なども格納することができます。

(同上より)

あぁ~、なんかややこしいなぁ。。 (+_+)

Empty 値 とはヘルプによると、

その変数が初期化されていないことを示し

Null 値とは、

その変数に有効なデータが格納されていないことを示します。

確認しておく。

    Dim hoge As Variant
    
    Debug.Print IsNull(hoge)   ' False
    Debug.Print IsEmpty(hoge)  ' True
    
    hoge = Null
    
    Debug.Print IsNull(hoge)   ' True
    Debug.Print IsEmpty(hoge)  ' False
    
    hoge = 0
    
    Debug.Print IsEmpty(hoge)  ' False
    
    Set hoge = Nothing
    
    Debug.Print IsNull(hoge)   ' False
    Debug.Print IsEmpty(hoge)  ' False