VBA SortedList Class

#SortedListClassの特徴、Arraylistとの違い
##同じ点
 - VBAではmscorlib.tlbで参照設定で使用可能になる
 - NET Frameworkがインストールされている必要があるが、大体つかえるらしい
 - Itemにオブジェクトも配列も入るので、ツリー上に増やせるSLstをPublicにして複数作り、クラスを複数作ればできないことはないが、やっている例はネットにはないと思われる。そんな複雑なことをするなら、データベースソフトを使うからであろう。
 - この特徴から使用が推奨されていない。
 - といいつつ13年以上使われている
 - VBSでも使える
##相違点
 - Arraylistと比較してソートしながら追加するため、速度が遅い。
 - 実体が配列なので挿入や削除にもソートされ、遅い。
 - SortedListの実装はソート済み配列リスト(C++でいうvector)
 - キーを検索するときは二分探索を行う
 - インデックスによる探索も可能(0からスタート)
 - Item,つまりキーの値が入っているかも確認できる。(Arraylistは自分で作る必要がある)
 - このインデックス番号は追加、削除でソートされ、固定したものではない
 - 逆順ソートはできない
 - ただしSortは追加した時点で行われるため、Sortする必要はない
 - HashtableとArraylistの両方の特徴を備えている。
 - Arraylistは可変長の配列に向く
## 注意点
### Keyは整数ではなく文字列がよい
なぜかというとAddを掛けるときにKeyの値が3だとIndexと解釈されるため。
上記の通りIndexは自動的に付加されるので、わざわざIndexをInteger,Longにする必要はない。

##参考
https://oshiete.goo.ne.jp/qa/701242.html
https://qiita.com/Q11Q/items/f33efb93d872b652eb49
[プロシージャ一覧を作成するマクロ ](https://www.relief.jp/docs/017861.html)
[SortedListとSortedDictionaryの違い](http://cyberboy6.blog.fc2.com/blog-entry-324.html)
[SortedListクラスを利用する](http://www.eurus.dti.ne.jp/~yoneyama/Excel/vba/vba_sortedlist.html)
[ExcelでのSortedList](http://acompass.net/top0/?EXCEL/SortedList)
[ジェネリックコレクション(3) SortedListとSortedDictionary](https://smdn.jp/programming/netfx/collections/2_generic_3_sortedlist_sorteddictionary/)

# Class Module
##機能一覧(予告なく変更するときがあります)
|Function/Sub|説明   |
|:-------------------:|:---------------------------------------------------------------------------------:|
| Class_Initialize||
| Class_Terminate||
| Add_sLst|key(object),Item(object)でListに追加できる。同じものは追加できない。また追加と同時にTrimToSizeで適正化する。成功したらTrueが返る。|
| clear_Slst|リストをクリアする|
| ContainsKey_sLst|Keyに同じ値があるか|
| ContainsValue_sLst|Itemに同じ値があるか（これはDictionaryやArraylistにはない）|
| Count_SLst|リストの数|
| IndexNum|Keyが0番からカウントして何番目か|
| IsFixedSize_SLst|固定長か|
| IsReadOnly_SLst|リードオンリーか|
| IsSyncro|スレッドセーフか|
| Remove_SLst|指定したキーを持つItemを SortedList オブジェクトから削除します。|
| Remove0StartIndex|インデックス番号で指定して削除する|
| ReplaceKeyValue|(IndexZeroStart, valueofkey)Indexにより指定したKeyの値を指定した値に置換します。|
| retCapacity_SLst|TrimToSizeで適正化したうえで、リストの容量を返す。|
| RetGetKeyInt32|番号で指定したkeyの値|
| RetIndexNumStartAt1|Keyの値を1番から始めたとすると何番目か|
| retKeyValue_SLst|インデックスで指定したKeyの値を返す|
| ShowImmidiateKeyAndValue|Key,Itemの組み合わせをイミディエイトに表示|

##Code
```visualbasic
Option Explicit
'Class Name = ClassSortedList
Dim i As Long
Dim SLst

'Dim SLst As mscorlib.SortedList
Dim x
Private Sub Class_Initialize()
Set SLst = CreateObject("System.Collections.SortedList")
'Set SLst = New SortedList
End Sub

Function Add_sLst(wordofkey, valueofkey)
If SLst Is Nothing Then Add_sLst = False: Exit Function
If SLst.contains(wordofkey) = False Then
SLst.Add wordofkey, valueofkey
SLst.trimtosize
Add_sLst = True
Exit Function
Else
Add_sLst = False
Exit Function
End If
End Function
Function ContainsValue_sLst(valueOfObject)
If SLst.containsvalue(valueOfObject) Then ContainsValue_sLst = True Else ContainsValue_sLst = False
End Function
Function ContainsKey_sLst(valueOfObject)
If SLst.contains(valueOfObject) Then ContainsKey_sLst = True Else ContainsKey_sLst = False
End Function
Function IsSyncro()
'オブジェクトへのアクセスが同期されている (スレッド セーフである) かどうかを示す
IsSyncro = CBool(SLst.IsSynchronized)
End Function
Function RetGetKeyInt32(Int32Index)
'０から始まるIndex番号によってKeyの値を返す
RetGetKeyInt32 = SLst.getkey(Int32Index)
End Function
Function RetIndexNumStartAt1(wordofkeyValue)
'wordofkeyが0からカウントして何番目なので1
RetIndexNumStartAt1 = SLst.indexofkey(wordofkeyValue) + 1
End Function
Function IndexNum(wordofkeyValue)
'wordofkeyが0からカウントして何番目か。キーの値でインデックスが返る。
IndexNum = SLst.indexofkey(wordofkeyValue)
End Function
Function Remove0StartIndex(IndexZeroStart)
SLst.RemoveAt IndexZeroStart
End Function
Sub clear_Slst()
SLst.Clear
End Sub
Function Remove_SLst(wordofkey)
'指定したキーを持つ要素を SortedList オブジェクトから削除します。
On Error Resume Next
If SLst Is Nothing Then Remove_SLst = False: Exit Function
If SLst.contains(wordofkey) Then SLst.Remove wordofkey: Remove_SLst = True: Exit Function
If Err.Number <> 0 Then Remove_SLst = False Else Remove_SLst = True
End Function
Function Count_SLst()
Count_SLst = SLst.Count
End Function

Function ReplaceKeyValue(IndexZeroStart, valueofkey)
'Indexにより指定したKeyをSortedList オブジェクトから置換します。
On Error Resume Next
SLst.setbyindex IndexZeroStart, valueofkey
ReplaceKeyValue = True
Exit Function
If Err.Number <> 0 Then ReplaceKeyValue = False: Exit Function
End Function
Function IsReadOnly_SLst()
IsReadOnly_SLst = SLst.IsReadOnly
End Function
Function IsFixedSize_SLst()
IsFixedSize_SLst = CBool(SLst.IsFixedSize)
End Function
Function RetCapacity_SLst()
SLst.trimtosize
RetCapacity_SLst = SLst.capacity
End Function
Function RetKeyValue_SLst(wordofkey)
RetKeyValue_SLst = SLst.Item(wordofkey)
End Function
Function ShowImmidiateKeyAndValue()
Dim i As Long
Dim arKey, arlist
For i = 0 To SLst.Count - 1
Debug.Print SLst.getkey(i) & "," & SLst.getbyindex(i)
Next
End Function
Private Sub Class_Terminate()
If Not SLst Is Nothing Then SLst.Clear: Set SLst = Nothing
End Sub
```

#標準モジュール

```visualbasic
Sub testLst()
Dim cLst As ClassSotedList
Set cLst = New ClassSotedList
Dim arlist
cLst.Add_sLst "Zion", vbNull
cLst.Add_sLst "England", "イギリス"
cLst.Add_sLst "USA", "アメリカ"
cLst.Add_sLst "China", "中華人民共和国" '中国は一番最後に追加されているが C,E,Uの順にソートされ、0番目になる
Debug.Print cLst.RetIndexNumStartAt1("USA")
Debug.Print cLst.RetGetKeyInt32(1)
Debug.Print cLst.ContainsValue_sLst("イギリス") 'Itemの値にイギリスが入っているか
cLst.ReplaceKeyValue 0, "英国" 'これで China 英国の組み合わせになる
Debug.Print cLst.Count_SLst
cLst.Remove_SLst (1)
Debug.Print cLst.RetKeyValue_SLst("China")
Stop
Debug.Print cLst.RetCapacity_SLst
Debug.Print cLst.IsSyncro
cLst.Add_sLst "Japan", "日本"
Debug.Print cLst.ShowImmidiateKeyAndValue
End Sub
Sub testLst2()
Dim cLst As ClassSotedList
Set cLst = New ClassSotedList
Dim arlist
cLst.Add_sLst "text", "a"
cLst.Add_sLst "Text", "b" '完全一致のため追加される
cLst.Add_sLst "text", "o" '重複しているため入らない
Debug.Print cLst.IndexNum("text")
Debug.Print cLst.Count_SLst
Debug.Print cLst.RetCapacity_SLst
Debug.Print cLst.IsSyncro
Debug.Print cLst.ShowImmidiateKeyAndValue
cLst.Add_sLst 3, "c" 'この場合3と書くとindexでアクセスしているためエラーになる
End Sub
```

#解説
##コンストラクター

|コンストラクター|説明   |
|:-----------------------------:|:----------------------------------------------------------------------------------------------------------------------:|
| SortedList()|空で、既定の初期量を備え、SortedList オブジェクトに追加された各キーによって実装されている IComparable インターフェイスに従って並べ替えられた、SortedList クラスの新しいインスタンスを初期化します。|
| SortedList(IComparer)|空で、既定の初期量を備え、指定した SortedList インターフェイスに従って並べ替えられた、IComparer クラスの新しいインスタンスを初期化します。|
| SortedList(IComparer, Int32)|空で、指定した初期量を備え、指定した SortedList インターフェイスに従って並べ替えられた、IComparer クラスの新しいインスタンスを初期化します。|
| SortedList(IDictionary)|指定したディクショナリからコピーした要素を格納し、コピーした要素の数と同じ初期量を備え、各キーによって実装されている SortedList インターフェイスに従って並べ替えられた、IComparable クラスの新しいインスタンスを初期化します。|
| SortedList(IDictionary, IComparer)|指定したディクショナリからコピーした要素を格納し、コピーした要素の数と同じ初期量を備え、指定した SortedList インターフェイスに従って並べ替えられた、IComparer クラスの新しいインスタンスを初期化します。|
| SortedList(Int32)|空で、指定した初期量を備え、SortedList に追加された各キーによって実装されている IComparable インターフェイスに従って並べ替えられた、SortedList クラスの新しいインスタンスを初期化します。|

##メソッド
|メソッド |説明   |
|:--------------------|:------------------------------------------------------------------|
| ***Add(Object, Object)***|指定したキーおよび値を持つ要素を SortedList オブジェクトに追加します。|
| ***Clear()***|SortedList オブジェクトからすべての要素を削除します。|
| Clone()|SortedList オブジェクトの簡易コピーを作成します。|
| ***Contains(Object)***|SortedList オブジェクトに特定のキーが格納されているかどうかを確認します。|
| ***ContainsKey(Object)***|SortedList オブジェクトに特定のキーが格納されているかどうかを確認します。|
| ***ContainsValue(Object)***|SortedList オブジェクトに特定の値が格納されているかどうかを確認します。|
| CopyTo(Array, Int32)|SortedList の要素を 1 次元の Array オブジェクトにコピーします。コピー操作は、配列内の指定したインデックスから始まります。|
| Equals(Object)|指定したオブジェクトが、現在のオブジェクトと等しいかどうかを判断します。|
| |(Inherited from Object)|
| ***GetByIndex(Int32)***|SortedList オブジェクトの指定したインデックスにある値を取得します。|
| GetEnumerator()|IDictionaryEnumerator オブジェクトを反復処理する SortedList オブジェクトを返します。|
| GetHashCode()|既定のハッシュ関数として機能します。(Inherited from Object)|
| ***GetKey(Int32)***|SortedList オブジェクトの指定したインデックスにあるキーを取得します。|
| GetKeyList()|SortedList オブジェクト内のキーを取得します。|
| GetType()|現在のインスタンスの Type を取得します。(Inherited from Object)|
| GetValueList()|SortedList オブジェクト内の値を取得します。|
| ***IndexOfKey(Object***)|SortedList オブジェクト内の指定したキーの、0 から始まるインデックス番号を返します。|
| ***IndexOfValue(Object)***|SortedList オブジェクト内にある指定した値のうち、最初に出現する値の、0 から始まるインデックス番号を返します。|
| MemberwiseClone()|現在の Object の簡易コピーを作成します。(Inherited from Object)|
| ***Remove(Object)***|指定したキーを持つ要素を SortedList オブジェクトから削除します。|
| ***RemoveAt(Int32)***|SortedList オブジェクトの指定したインデックスにある要素を削除します。|
| SetByIndex(Int32, Object)|SortedList オブジェクトの特定のインデックスにある値を置換します。|
| Synchronized(SortedList)|SortedList オブジェクト用の同期された (スレッド セーフな) ラッパーを返します。|
| TrimToSize()|容量を SortedList オブジェクト内にある実際の要素数に設定します。|

##プロパティ

|プロパティ|説明   |
|:---------|:--------------------------------------------------------|
| ***Capacity***|SortedList オブジェクトの容量を取得または設定します。|
| ***Count***|SortedList オブジェクトに格納されている要素の数を取得します。|
| ***IsFixedSiz***e|SortedList オブジェクトが固定サイズかどうかを示す値を取得します。|
| ***IsReadOnly***|SortedList オブジェクトが読み取り専用かどうかを示す値を取得します。|
| ***IsSynchronized***|SortedList オブジェクトへのアクセスが同期されている (スレッド セーフである) かどうかを示す値を取得します。|
| ***Item[Object]***|SortedList オブジェクト内の特定のキーに関連付けられている値を取得または設定します。|
| ***Keys***|SortedList オブジェクト内のキーを取得します。|
| SyncRoot|SortedList オブジェクトへのアクセスを同期するために使用できるオブジェクトを取得します。|
| ***Values***|SortedList オブジェクト内の値を取得します。|