空腹おやじのログと備忘録

VBA(主にExcel)でいろいろな実験的な事とか、Linuxのコマンドとか設定とかについて忘れないように、あれこれと・・・

VBAのDictionaryに配列を格納して、変更してみる

どうせなので、多次元配列(3次元だけど)にしてみた。
テスト用データ
f:id:Z1000S:20180930164204j:plain

その1 配列を格納してみる

Public Sub Dictionaryに配列を追加()

    Dim dicValues   As Dictionary
    Dim lValues(1, 1, 1) As Long
    Dim lKey  As Long
    Dim i   As Long
    Dim j   As Long
    Dim k   As Long

    Set dicValues = New Dictionary

    With ThisWorkbook.Worksheets("Sheet2")
        For i = 2 To 9
            lValues(.Cells(i, 1).Value, .Cells(i, 2).Value, .Cells(i, 3).Value) = .Cells(i, 4).Value
        Next i

        'キー値 0で配列を追加
        dicValues.Add 0, lValues

        Erase lValues

        For i = 10 To 17
            lValues(.Cells(i, 1).Value - 2, .Cells(i, 2).Value, .Cells(i, 3).Value) = .Cells(i, 4).Value
        Next i

        'キー値 1で配列を追加
        dicValues.Add 1, lValues
    End With

    '
    Debug.Print "Dictionary.Itemは配列?:" & IsArray(dicValues.Item(0))
    Debug.Print

    For lKey = 0 To dicValues.Count - 1
        Debug.Print "キー:" & CStr(lKey)

        For i = 0 To UBound(lValues, 1)
            For j = 0 To UBound(lValues, 2)
                For k = 0 To UBound(lValues, 3)
                    Debug.Print i; j; k, dicValues.Item(lKey)(i, j, k)
                Next k
            Next j
        Next i
    Next lKey

End Sub

実行してみる。

call Dictionaryに配列を追加
Dictionary.Itemは配列?:True

キー:0
0 0 0 10000
0 0 1 10001
0 1 0 10010
0 1 1 10011
1 0 0 10100
1 0 1 10101
1 1 0 10110
1 1 1 10111
キー:1
0 0 0 20200
0 0 1 20201
0 1 0 20210
0 1 1 20211
1 0 0 20300
1 0 1 20301
1 1 0 20310
1 1 1 20311

dicValues.Item(lKey) これ自体は配列なんですね。
だから、dicValues.Item(lKey)(i, j, k)という形でアクセス出来るんですね。

その2 追加した配列をまるまる置き換えてみる

Public Sub Dictionaryに追加した配列をまるまる置換()

    Dim dicValues   As Dictionary
    Dim lValues(1, 1, 1) As Long
    Dim lKey    As Long
    Dim i   As Long
    Dim j   As Long
    Dim k   As Long

    Set dicValues = New Dictionary

    With ThisWorkbook.Worksheets("Sheet2")
        For i = 2 To 9
            lValues(.Cells(i, 1).Value, .Cells(i, 2).Value, .Cells(i, 3).Value) = .Cells(i, 4).Value
        Next i

        '同じ配列をキー値 0と1で追加
        dicValues.Add 0, lValues
        dicValues.Add 1, lValues

        For i = 10 To 17
            lValues(.Cells(i, 1).Value - 2, .Cells(i, 2).Value, .Cells(i, 3).Value) = .Cells(i, 4).Value
        Next i

        'キー値 1のItemを値の異なる配列で書き換え
        dicValues.Item(1) = lValues
    End With

    For lKey = 0 To dicValues.Count - 1
        Debug.Print "キー:" & CStr(lKey)

        For i = 0 To UBound(lValues, 1)
            For j = 0 To UBound(lValues, 2)
                For k = 0 To UBound(lValues, 3)
                    Debug.Print i; j; k, dicValues.Item(lKey)(i, j, k)
                Next k
            Next j
        Next i
    Next lKey

End Sub

実行してみる。

call Dictionaryに追加した配列をまるまる置換
キー:0
0 0 0 10000
0 0 1 10001
0 1 0 10010
0 1 1 10011
1 0 0 10100
1 0 1 10101
1 1 0 10110
1 1 1 10111
キー:1
0 0 0 20200
0 0 1 20201
0 1 0 20210
0 1 1 20211
1 0 0 20300
1 0 1 20301
1 1 0 20310
1 1 1 20311

きちんと置き換わっている。

その3 ”追加した配列の要素”だけ変更出来るか?

Public Sub Dictionaryに追加した配列の要素を変更()

    Dim dicValues   As Dictionary
    Dim lValues(1, 1, 1) As Long

    Set dicValues = New Dictionary

    With ThisWorkbook.Worksheets("Sheet2")
        'キー値 0で無変更の配列を追加
        dicValues.Add 0, lValues

        'キー指定して、配列の要素を変更
        dicValues.Item(0)(0, 0, 0) = .Cells(10, 4).Value

        If dicValues.Item(0)(0, 0, 0) <> .Cells(10, 4).Value Then
            Debug.Print "Not equal! orz " & vbCrLf; dicValues.Item(0)(0, 0, 0); .Cells(10, 4).Value
        End If
    End With

End Sub

実行してみる。

call Dictionaryに追加した配列の要素を変更
Not equal! orz
0 20200

値は変わっていない。
dicValues.Item(0)を内容の異なる配列で上書きすることは出来るけれど
その要素dicValues.Item(0)(0, 0, 0)を書き換える事は出来ないみたい。
エラーは出ずに処理は終了するんだけどねぇ・・・
読み取り専用のような感じ。

やっぱり一旦データを変数に取り出して、編集後に再度設定するしかないのかもしれない。