Home » エクセルマクロ・Excel VBAの使い方 » 配列 » Byte配列のFor Eachループでの動きをVarPtr・TypeNameで確認する

Byte配列のFor Eachループでの動きをVarPtr・TypeNameで確認する

対象:Excel2007, Excel2010, Excel2013, Windows版Excel2016

Byte配列のFor Eachループでの動きをVarPtr・TypeNameで確認する

「vba for each byte配列」
という検索で、このサイト・インストラクターのネタ帳へのアクセスがありました。

VBA(Visual Basic for Applications)で、Byte型の配列を、For Each~Nextループで処理する方法に関して、調べていた方による検索キーワードです。

[スポンサードリンク]

For Each~Nextループで配列の要素を受ける変数はバリアント型

以下のようなプロシージャを作成されたのでしょうか。

Sub Byte配列の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

End Sub

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配列を処理するときの状態を確認しましょう。

Sub Byte配列のForループ()

 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

上記のマクロを実行すると、以下のような出力がイミディエイトウィンドウに行われます。

Byte配列のFor Eachループでの動きをVarPtr・TypeNameで確認する

配列要素の型と、
    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ループです。

Sub Byte配列のFor_Eachループ()

 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

上記のマクロを実行した結果は以下のとおりです。

Byte配列のFor Eachループでの動きをVarPtr・TypeNameで確認する

最初の、
 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で確認する

「配列」の記事一覧

検索


Copyright © インストラクターのネタ帳 All Rights Reserved.

.