Excel2002のVBAでキーと値のリストを使用する。

いわゆるjava.util.Vector

ExcelVBAのCollectionで実装できるのかと思いきや

  1. 値の再セットができない。
  2. 文字をキーにすると設定順(add()した順)にならない。
  3. そもそもadd()で2バイト文字を入れるとエラーになる。

っつーどうしようもないエラーが出てくれちゃって、にっちもさっちも行かないので自力で実装。

データ用構造体の作成

と、言いつつ構造体じゃない。
ってのは構造体(type...end type)で宣言したものはfor eachで取得できないからだそうだ。何だそれ。

ってことでクラスモジュールを使う。

クラスモジュール[VectorData]
Public key As String
Public value As Variant
VectorData 解説

キーと値を保持。解説も必要ないな。
本当はキーもVariantにしたかったんだけど、扱い面倒だわ処理速度は遅いわで良いこと無いんでStringに限定。

つかクラスの名が泣くわっ。

Vector本体の作成

必要な機能は、

  1. キーと値ペアでの保持
  2. 挿入序列の保持
  3. キーコレクションの取得
  4. 既存データの書き換え

なので、必要なメソッドをさくっと作成。

クラスモジュール[Vector]

Public list As New Collection


Sub init()
    If Me.list Is Nothing Then
        Set Me.list = New Collection
    End If
End Sub

Function add(key As String, value As Variant)
    Dim data As New VectorData
    
    Call Me.init
    data.key = key
    data.value = value
    
    Call Me.list.add(data)
    add = Me.list.count
End Function

Function getValue(key As String) As Variant
    Dim data As VectorData
    Call Me.init
    
    For Each data In Me.list
        If data.key = key Then
            getValue = data.value
        End If
    Next
End Function

Function count() As Long
    count = Me.list.count
End Function


Function exists(key As String) As Boolean
    Dim data As VectorData
    Call Me.init
    
    If Me.list Is Nothing Then
        Set Me.list = New Collection
    End If
    
    For Each data In Me.list
        If data.key = key Then
            exists = True
            Exit Function
        End If
    Next
End Function

Function keys() As Collection
    Dim result As New Collection
    Call Me.init
    
    For Each data In Me.list
        Call result.add(data.key)
    Next
    
    Set keys = result
End Function

Sub setValue(key As String, value As Variant)
    Dim data As VectorData
    Call Me.init
    
    For Each data In Me.list
        If data.key = key Then
            data.value = value
            Exit Sub
        End If
    Next
    
    Call Me.add(key, value)
End Sub
VectorData 解説

Public list As New Collection

データ保持用のコレクション。
本当はpublicである必要はまるで無い。
要するに面倒だったってことだ。:-P

init()

コレクション初期化用メソッド。
本来はコンストラクタをオーバーライドするんだけど面倒だった。
反省はしてない。

add(key As String, value As Variant)

データを追加する。
パラメータはキーと値。
キーの重複チェックはしてない。
本来は必要だけど面倒d(ry

追加したデータのインデックスを返す。
しかし使い道は無い( ´,_ゝ`)

getValue(key As String) As Variant

値の取得
指定したキーが存在しない場合Nothing*1が返る。

count() As Long

まんまcollection.count

exists(key As String) As Boolean

キーの存在チェック。
あんまり使う必要ないかも。
どっちかっつーと内部用のメソッド

keys() As Collection

キーのコレクションを返す。
データのクローリングに使う。

setValue(key As String, value As Variant)

値のセット。
普通はこっちを使ってaddは使わない。

見てのとおりやっつけで適当なのだ。

使い方
dim list as new Vector
dim key as variant

' 追加
list.set("Japan","tokyo")
list.set("USA","Washington")
list.set("England","London")

' 取り出し
For Each key In list.keys
    msgBox( key & " = " & list.getValue(CStr(key))  )
Next

*1:いわゆるnull