私が正しく理解していれば、必要なものはインデックス付きの並べ替えです。多くの言語では、索引ソートが標準機能として提供されています。 VBAにはソートもインデックス付きソートも標準ではありません。
従来の配列ソートの場合、値は配列内でソートされます。例えば:私はソートにその配列を渡す場合
A D B E C
、それは次のように返されます:
A B C D E
しかし、時にはあなたは配列をソートすることはできません、私は値を持つ配列があるとします。あなたの場合、配列は列見出しの範囲です。これらの見出しは列に属しているため、並べ替えることはできません。列の順序は何かを意味するので、実際には不可能でおそらく容認できない列を並べ替える必要があります。
は、これらの両方の配列は変わらないキーを出てソートするソートに渡され
Keys A D B E C
Indices 1 2 3 4 5
指標が与える:インデックス付きソートして
は、あなたは配列のキーとインデックスを作成して
Indices 1 3 5 2 4
通常の並べ替えでは、並べ替えられたエントリにArray(1)
としてアクセスします。 Array(2)
など。インデックス付きソートでは、ソートされたエントリにArray(Indices(1))
としてアクセスします。 Array(Indices(2))
など。
ソートされたエントリを取得するためにインデックスを使用することは、最初は分かりにくいことがあります。間違いなく、ソース配列に直接行くことは間違いありません。
以下、私はあなたにインデックス付き挿入ソートを与えました。挿入ソートは簡単で分かりやすいですが、エントリ数が多い場合は遅いです。ソートするエントリは5つしかないため、パフォーマンスは許容されます。 "Insertion Sort"のWikiエントリーを見て、それがどのように機能するかの絵デモンストレーションをしてください。
マクロDemoSortColumnHeadings
は、並べ替えの使い方と列見出しへのアクセス方法を示しています。私はこれがDemoSortColumnHeadings
をより理解しやすくすると信じているので、Keys
の代わりにColHeads
とColNums
の代わりにIndices
の名前を使用しました。ソートされたColNums
には、必要なシーケンス内の列番号が含まれています。ソート後、配列ColHeads
は必要なくなりました。
最後の1つです。 VBAは、配列の下限と上限を指定できる唯一の言語です。ほとんどの言語では、下限はゼロにする必要があります。私はこれを利用して、配列の次元を(2〜6)と定義し(0〜4)定義しませんでした。このため、配列ColNums
の値は列番号です。ほとんどの言語では、列番号を取得するためにColNums(N)+2が必要でした。
Option Explicit
Sub DemoSortColumnHeadings()
Const ColFirst As Long = 2 ' Column B = column 2
Const ColLast As Long = 6 ' Column F = column 6
Dim ColCrnt As Long
Dim ColNums() As Long
Dim InxColNum As Long
Dim ColHeads() As String
With Worksheets("Test data")
ReDim ColHeads(ColFirst To ColLast)
ReDim ColNums(ColFirst To ColLast)
For ColCrnt = ColFirst To ColLast
ColHeads(ColCrnt) = .Cells(1, ColCrnt).Value
ColNums(ColCrnt) = ColCrnt
Next
Debug.Print "Initial sequence"
Debug.Print "|";
For ColCrnt = ColFirst To ColLast
Debug.Print .Cells(1, ColCrnt).Value & "|";
Next
Debug.Print
Call InsertionSort(ColNums, ColHeads)
Debug.Print "Final sequence"
Debug.Print "|";
For InxColNum = LBound(ColNums) To UBound(ColNums)
ColCrnt = ColNums(InxColNum)
Debug.Print .Cells(1, ColCrnt).Value & "|";
Next
Debug.Print
End With
End Sub
Public Sub InsertionSort(ByRef Indices() As Long, ByRef Keys() As String)
Dim Found As Boolean
Dim I As Long
Dim InxIFwd As Long
Dim InxIBack As Long
For InxIFwd = LBound(Indices) + 1 To UBound(Indices)
I = Indices(InxIFwd) ' Save value of current entry in Indices
' Find first entry back, if any, such that Keys(I) >= Keys(Indices(InxIBack))
' If Keys(I) < Keys(Indices(InxIBack)), set Indices(InxIBack+1) to
' Indices(InxIBack). That is move indices for keys greater that Keys(I) down
' Indices leaving a space for I nearer the beginning.
Found = False
For InxIBack = InxIFwd - 1 To LBound(Indices) Step -1
If Keys(I) >= Keys(Indices(InxIBack)) Then
' Keys(I) belongs after Keys(Indices(InxIBack))
Indices(InxIBack + 1) = I
Found = True
Exit For
End If
Indices(InxIBack + 1) = Indices(InxIBack)
Next
If Not Found Then
' Insertion point for I not found so it belongs at beginning of Indices
Indices(LBound(Indices)) = I
End If
Next
End Sub
あなたのアプローチからコードを投稿してください。 – Limak