前回が今年の最後にするつもりだったのですが、気になる事があったので
これを最後にします。
VBAでコレクションや配列をソートしたい場合基本的には無く、単調なものであれば
DotNetのArrayListを利用する事も考えるのですが、ちょっと単調ではない
条件(プロパティで とか)でソートする場合、ゴリゴリ書くしか方法がやはり無いん
ですね。
非常に参考になったのがこちらのt-hom'sさんのサイト
これを流用させてもらおうと思ったのですが、案の定CATIAのApplicationクラス
にはRunメソッド無いんですよ・・・。
好み的な部分も有り、こんな感じにしてみました。
(データが整数って言うのが、無意味に近いのですが)
'vba Collection_BubbleSort_Test Sub Collection_BubbleSort_Test() Const Min = 1& '最小値 Const Max = 100& '最大値 Const Count = 10& '数 Dim lst As Collection: Set lst = New Collection Dim i& For i = 0 To Count lst.Add Fix((Max - Min + 1) * Rnd + 1) Next Debug.Print "-- Before --" Call Dump(lst) Debug.Print "-- Aafter --" Call B_Sort_List(lst) Call Dump(lst) Debug.Print "-- End --" End Sub 'ソート条件 True-降順 False-昇順 Private Function Comparison(ByVal A As Variant, ByVal B As Variant) As Boolean Comparison = A > B End Function 'BubbleSort_Collection Private Sub B_Sort_List(ByRef List As Collection) Dim i&, j& For i = 1 To List.Count For j = List.Count To i Step -1 If Comparison(List(i), List(j)) Then CollectionSwap List, i, j End If Next j Next i End Sub 'Collection用スワップ Private Sub CollectionSwap(ByRef List As Collection, ByVal Idx1&, ByVal Idx2&) Dim Item1, Item2 With List If IsObject(.Item(Idx1)) Then Set Item1 = .Item(Idx1) Set Item2 = .Item(Idx2) Else Let Item1 = .Item(Idx1) Let Item2 = .Item(Idx2) End If .Add Item1, After:=Idx2 .Remove Idx2 .Add Item2, After:=Idx1 .Remove Idx1 End With End Sub 'Debug Private Sub Dump(ByVal lst) Dim l For Each l In lst Debug.Print l Next End Sub
キモは、Comparison関数です。バブルソート内の IF文 で、True か False を返す
関数さえ作ってしまえば良いのかな? と思いました。
上記では昇順ですが、降順にしたい場合はComparison関数内を
Comparison = A < B
に、するだけです。
但し、t-hom'sさんのサンプルほど汎用性が無いんです。複数の異なる条件でソート
したい場合は、NGなんです・・・。
それを考えると Ariawase の Funcクラスを利用し
Private Sub B_Sort_List(ByRef List As Collection, ByVal fun As Func) ・・・
の様にし、ソート条件用の関数さえ用意しておけば、異なる条件化で
ソート出来る様になるんじゃないのかな? と思ったりしてます。(未確認です)
悩む・・・。 良いお年を。