「vba for each byte配列」
という検索で、このサイト・インストラクターのネタ帳へのアクセスがありました。
VBA(Visual Basic for Applications)で、Byte型の配列を、For Each~Nextループで処理する方法に関して、調べていた方による検索キーワードです。
For Each~Nextループで配列の要素を受ける変数はバリアント型
以下のようなプロシージャを作成されたのでしょうか。
Const TXT = "イロハ"
Dim itm As Byte
Dim arr() As Byte
arr = TXT
For Each itm In arr
Debug.Print itm
Next itm
Byte型の配列なのだから、個々の要素を受ける変数もByte型で良さそうに思ってしまうかもしれませんが、Variantでなければダメです。VBAのFor Each~Nextループの仕様が、そう決まっているので仕方ありません。
For Each~Nextループで、個々の要素を受ける変数を、
Dim itm As Byte
としている部分を
Dim itm As Variant
とすれば、問題なく動くようになります。
ですが、何となく残る気持ち悪さは、私も理解できます。
Byte配列のFor~Nextループでの動きをVarPtr関数・TypeName関数で確認する
Byte型配列を使うレベルの方であれば、TypeName関数で型を調べたり、VarPtr関数を使ってメモリのアドレスを調べたりすると、その気持ち悪さが軽減されるかもしれません。
まず、カウンター変数を使うFor~Nextループで、Byte配列を処理するときの状態を確認しましょう。
Const TXT = "イロハ"
Dim i As Long
Dim arr() As Byte
arr = TXT
For i = LBound(arr) To UBound(arr)
Debug.Print _
TypeName(arr(i)) & vbTab & _
VarPtr(arr(i)) & vbTab & _
arr(i)
Next i
Debug.Print String(24, "-")
End Sub上記のマクロを実行すると、以下のような出力がイミディエイトウィンドウに行われます。
配列要素の型と、
TypeName(arr(i)) & vbTab & _
配列要素のメモリアドレスと、
VarPtr(arr(i)) & vbTab & _
配列要素の値が、
arr(i)
Debug.Printされています。
配列要素の型はもちろんすべて「Byte」です。
注目していただきたいのは、メモリアドレスが、キレイに1バイトずつ増えているということです。
配列はメモリ上ではキレイに並んでいることがよく見えます。
配列をFor~Nextループで回す場合、キレイに並んだこれらの値を順番に処理していることが見えます。
Byte配列のFor Each~Nextループでの動きをVarPtr関数・TypeName関数で確認する
For~Nextループの動きを確認できたら、本題のFor Each~Nextループです。
Const TXT = "イロハ"
Dim itm As Variant
Dim arr() As Byte
Debug.Print _
TypeName(itm) & vbTab & _
VarPtr(itm)
arr = TXT
For Each itm In arr
Debug.Print _
TypeName(itm) & vbTab & _
VarPtr(itm) & vbTab & _
itm
Next itm
Debug.Print String(24, "-")
End Sub上記のマクロを実行した結果は以下のとおりです。
最初の、
Debug.Print _
TypeName(itm) & vbTab & _
VarPtr(itm)
で出力された結果が「Empty 1634468」となっています。
変数・itmは、
Dim itm As Variant
とVariantで宣言されていますが、まだ何の格納も行われていないので、TypeName関数で返される型は「Empty」となっています。
ところがFor Each~Nextループに入ったあとでは、Byte配列から要素を受けたために型が「Byte」となっています。
そして、VarPtr関数で出力したメモリアドレスは、一切変化していません。
配列の各要素はメモリ上では順番に無駄なく並んでいて、For Each~Nextループの変数は、このキレイに並んだ配列要素の値を受け取るための変数で、メモリアドレスが変化することはないということです。
このような動きを見ると、For Each~Nextループで配列を処理する際に、変数がバリアント型でなければならない気持ち悪さが、多少は軽減されるのではないでしょうか。
Home » エクセルマクロ・Excel VBAの使い方 » 配列 » Byte配列のFor Eachループでの動きをVarPtr・TypeNameで確認する