配列をソートする


Excel VBAで配列をソートするには2つの方法があります。1つは、VBAというより「一般的なプログラミングテクニック」のひとつであるクイックソートです。任意の配列(または複数の要素)を並べ替えるというロジック(考え方)は、大昔からいろいろな方法が提唱されています。私はあまり詳しくありませんが、クイックソート以外にもバブルソートなどがあったかと。興味がある方はgoogleなどで調べてみてください。クイックソートはロジック(考え方)ですから、もちろんVBAで使用することも可能です。

次のコードは、ランダムな数字を格納した配列をソートします。数値は3桁としました。Rnd関数の乱数を使います。とりあえず要素数は1000個としました。乱数を生成した段階で先頭の10件を記録し、クイックソートした後の配列から先頭の10件を取得します。「先頭10件」を見ているのは、要素が1000件くらいないと速度が体感できないでしょうし、かといって1000件のソート結果をすべて見るのは大変だからです(^^;

Sub QuickSort()
    Dim i As Long, j As Long, msg As String
    Dim swap As Long, Numbers(1000) As Long
    For i = 1 To 1000                           ''ランダムな数字が格納された配列を生成する
        Numbers(i) = Int(Rnd * 900) + 100
    Next i
    msg = msg & "【Before Sort】" & vbCrLf      ''ソート前の結果(先頭から10件)を取得する
    For i = 1 To 10
        msg = msg & Numbers(i) & vbCrLf
    Next i
    For i = 1 To 1000       ''ソート開始
        For j = 1000 To i Step -1
            If Numbers(i) > Numbers(j) Then
                swap = Numbers(i)
                Numbers(i) = Numbers(j)
                Numbers(j) = swap
            End If
        Next j
    Next i
    msg = msg & "【After Sort】" & vbCrLf       ''ソート後の結果(先頭から10件)を取得する
    For i = 1 To 10
        msg = msg & Numbers(i) & vbCrLf
    Next i
    MsgBox msg      ''結果を表示する
End Sub

2つめは、Excelの並べ替え機能を使う方法です。日頃からVBAを好み、何かというとすぐVBAで問題を解決したがるヘビーユーザーさんはご存じないかもしれませんが、Excelにはデータを並べ替える機能があるんです。配列内の要素を並べ替えたいのでしたら、その要素を一度ワークシートに書き出し、ワークシート上のデータを並べ替えた後で配列に戻せばいいんです。本当は、こちらの方がExcelらしいロジックだと思います。

次のコードは、上と同じことをExcelの並べ替え機能でやります。

Sub ExcelSort()
    Dim i As Long, msg As String, Numbers(1000) As Long
    For i = 1 To 1000                           ''ランダムな数字が格納された配列を生成する
        Numbers(i) = Int(Rnd * 900) + 100
    Next i
    msg = msg & "【Before Sort】" & vbCrLf      ''ソート前の結果(先頭から10件)を取得する
    For i = 1 To 10
        msg = msg & Numbers(i) & vbCrLf
    Next i
    For i = 1 To 1000       ''配列の要素をシートに書き込む
        Cells(i, 1) = Numbers(i)
    Next i
    ''シートをソートする
    Range("A1:A1000").Sort Key1:=Range("A1"), _
                           Order1:=xlAscending, _
                           Header:=xlGuess
    For i = 1 To 1000       ''結果を配列に戻す
        Numbers(i) = Cells(i, 1)
    Next i
    msg = msg & "【After Sort】" & vbCrLf       ''ソート後の結果(先頭から10件)を取得する
    For i = 1 To 10
        msg = msg & Numbers(i) & vbCrLf
    Next i
    MsgBox msg      ''結果を表示する
End Sub

ここでは作業用としてアクティブシートのA列を使いました。

ワークシートの並べ替え機能を使って配列要素をソートするときに注意しなければいけないのは、要素の型です。今回のように「3桁の数値」でしたら、セルに書き出しても数値のままですが、たとえば「2-1」などの文字列はセルに入れると日付と認識されてしまいます。あるいは「=」で始まる文字列は数式と認識されますので、数式として有効な文字列でないとエラーになります。

また、Excelの並べ替え機能は、各種の設定が次回にも引き継がれます。VBAから実行した並べ替えの設定は、次回手動で並べ替えるときのデフォルトになりますのでお気を付けください。

(追記)

某ブログで「これはクイックソートじゃないよ!」とご指摘を受けました。ありがとうございます。実は「クイックソート」という名称には自信ありませんでした(^^;誤ったことを書いてすいませんでした。