具体的にはJavascriptで同じ様なテーマで、連想配列をWithで使う以下の様な方法を書いてたサイトがあったので、これをvbaで実現することにした。
with ({a:0}) {
この中では a は有効。
}
withを抜けると a は参照不可。
そしてvbaで連想配列を返す関数は以下の通り。
Function TempDim(ByVal Dimension As String, Optional Parent As Object) As Object
'Dimension:変数宣言をカンマ区切りの文字列で行う。ex.)"TempNo,Name"
'Parent:ネストする場合、子のWith内では親の連想配列が参照できないので、
' パラメータとして渡す。
Dim sc As Object
Dim hash As Object
Dim i As Long
Dim v() As String
Set sc = CreateObject("ScriptControl")
sc.Language = "JScript"
sc.AddCode "function SetValue(hash, key, value) " & _
"{j=hash ? hash : {};j[key]=value;return j;}"
v = Split(Dimension, ",")
For i = LBound(v) To UBound(v)
Set hash = sc.CodeObject.SetValue(hash, v(i), Null)
Next i
Set hash = sc.CodeObject.SetValue(hash, "Me", hash)
If Not Parent Is Nothing Then
Set hash = sc.CodeObject.SetValue(hash, "Parent", Parent)
End If
Set TempDim = hash
End Function
そして以下の様に使用する。
宣言した名前はプロパティになるので、With内で頭にピリオドを付けて使用する。
With TempDim("i,j")
.i = 1
.j = 1
Do Until .i > 3
Debug.Print "親ループ i="; .i
Debug.Print "親ループ j="; .j
With TempDim("i", .Me) 'Meは自身を参照する
.i = 1
Do Until .i > 3
Debug.Print "子ループ i="; .i
.i = .i + 1
'Parentはパラメータで渡された親の連想配列
.Parent.j = .Parent.j + 1
Loop
End With
.i = .i + 1
Loop
End With
使用上の注意
- For文のカウンターには使えない。
For文のカウンターは変数でなければならず、この方法ではオブジェクトのプロパティとなるため使えない。 - プロパティ名は大文字小文字が区別される。
JScriptの機能で連想配列を実現してるのでJScriptの制限を受ける。VBエディタの変数名の自動修正機能に注意! - Variant型のみ
連想配列に型が無いためそうなる。あと上の関数では初期値をNULLにしている。