こんにちは! 健史です。
ソート処理の動きを わかりやすく目で見て確認できるように作成してみました。
紹介するソートは「選択ソート」と「バブルソート」で、比較回数は多く非効率らしいですが処理ロジックは単純です。
処理概要は、セルA1~A10までの値を昇順、すなわち小さい順にソートします。
尚この記事は、Excel-VBAを起動して貼り付ければ動作することを目指しています。
Excel-VBAの構造、起動方法、実行方法などを理解されていない方は、以下の記事を参照しながら一度やってみてから対応されることをお勧めします。
実行中に発生したエラーの対処法は、上記記事の2.エラーが発生したときの対処法に記載しています。(この段落のリンクから直接遷移します)
選択ソート
1.Excelを起動し、データをシート1の[A]列に貼り付け
コピーしてペーストするときは、Excelシートのセル:A1で[右クリック]-[形式を選択して貼り付け(S)]から[貼り付ける形式(A)]に"テキスト"を選択します。
10 9 8 7 6 5 4 3 2 1
再実行する際、このサイトから何度もコピーしなくてもよいように[E]列にも貼り付けておくと便利かと思います。
2.Alt+F8でVBAを起動してプログラムを貼り付け
VBAを起動後作成(C)ボタンをクリックし、[名前]に”sort1”など入力して貼り付けます。
Dim ix1, ix12, ix1_max, temp As Long Dim cnt1, cnt2 As Long cnt1 = 0 cnt2 = 0 ix1_max = Sheets(1).Range("A1").End(xlDown).Row Sheets(1).Columns(2).Clear Sheets(1).Columns(3).Clear For ix1 = 1 To ix1_max - 1 For ix12 = ix1 + 1 To ix1_max Sheets(1).Cells.ClearFormats Sheets(1).Cells(ix1, 1).Interior.Color = vbCyan Sheets(1).Cells(ix12, 1).Interior.Color = vbYellow '比較位置を目視で確認するために1秒ごとに停止する Application.Wait [Now()] + 1000 / 86400000 cnt1 = cnt1 + 1 If Sheets(1).Cells(ix1, 1) > Sheets(1).Cells(ix12, 1) Then temp = Sheets(1).Cells(ix1, 1) Sheets(1).Cells(ix1, 1) = Sheets(1).Cells(ix12, 1) Sheets(1).Cells(ix12, 1) = temp cnt2 = cnt2 + 1 End If Next Sheets(1).Cells(ix1, 2) = "←確定" Next Sheets(1).Cells.ClearFormats Sheets(1).Cells(1, 3) = cnt1 Sheets(1).Cells(2, 3) = cnt2
3.VBAエディタ画面を小さくして、シート1が見えるように配置
少なくとも、A列とB列が見えるように配置します。
4.VBAエディタ画面をカレントにして、[F5]キーを押して実行
上記3.で小さくした後であればカレントになっていますが、どこか違う画面をクリックしてしまった場合は[VBAエディタ画面]をクリックしカレントにしてから[F5]キーを押して実行します。
処理が開始し、シート1の内容が変わっていきます。
シアン色のセルを選択(固定)し、イエロー色のセルと比較し、イエロー色の値が小さければ内容を入れ替えます。
すべての値と比較を終えた選択セル(固定)は、B列に"←確定"がセットされていきます。
セルC1には「比較回数」、C2には「入れ替え回数」をセットしています。
[Application.Wait [Now()] + 1000 / 86400000]は、プログラムを停止するコマンドです。
時刻を指定するこもできますが、この場合は停止時間の単位を指定する記述です。
分子は1000ミリ秒すなわち1秒、分母の86400000は24時間をミリ秒換算した値です。
ちなみに[1 / 86400]や[0.5 / 86400]としても動作します。
5.オリジナルのプログラム
上記のプログラムから「処理内容を見える化した部分」を削除したオリジナルプログラムです。
Sub test() Dim ix1, ix12, ix1_max, temp As Long ix1_max = Sheets(1).Range("A1").End(xlDown).Row For ix1 = 1 To ix1_max - 1 For ix12 = ix1 + 1 To ix1_max If Sheets(1).Cells(ix1, 1) > Sheets(1).Cells(ix12, 1) Then temp = Sheets(1).Cells(ix1, 1) Sheets(1).Cells(ix1, 1) = Sheets(1).Cells(ix12, 1) Sheets(1).Cells(ix12, 1) = temp End If Next Next End Sub
1行目のセルを固定しておき、2行目以降のセルと全部比較していくと、最も小さい値が1行目にセットされます。
次に、2行目のセルを固定しておき、3行目以降のセルと全部比較していくと、2番目に小さい値が2行目にセットされます。
上記処理を、最大行からマイナス1した行まで繰り返します。
最大行からマイナス1した行までにする意味は、選択(固定)した値と比較する対象がプラス1した以降になるからで、プラス1した行が最大行になる、最大行にしなければならないからです。
バブルソート
1.実行手順やデータは選択ソートを参照・引用
実行手順やデータは選択ソートと同じ、プログラムのみが異なります。
Dim ix1, ix12, ix1_max, temp As Long Dim cnt1, cnt2 As Long cnt1 = 0 cnt2 = 0 ix1_max = Sheets(1).Range("A1").End(xlDown).Row Sheets(1).Columns(2).Clear Sheets(1).Columns(3).Clear For ix1 = 1 To ix1_max - 1 For ix12 = ix1_max - 1 To ix1 Step -1 Sheets(1).Cells.ClearFormats Sheets(1).Cells(ix12, 1).Interior.Color = vbCyan Sheets(1).Cells(ix12 + 1, 1).Interior.Color = vbYellow '比較位置を目視で確認するために1秒ごとに停止する Application.Wait [Now()] + 1000 / 86400000 cnt1 = cnt1 + 1 If Sheets(1).Cells(ix12, 1) > Sheets(1).Cells(ix12 + 1, 1) Then temp = Sheets(1).Cells(ix12, 1) Sheets(1).Cells(ix12, 1) = Sheets(1).Cells(ix12 + 1, 1) Sheets(1).Cells(ix12 + 1, 1) = temp cnt2 = cnt2 + 1 End If Next Sheets(1).Cells(ix1, 2) = "←確定" Next Sheets(1).Cells.ClearFormats Sheets(1).Cells(1, 3) = cnt1 Sheets(1).Cells(2, 3) = cnt2
2.オリジナルのプログラム
Dim ix1, ix12, ix1_max, temp As Long ix1_max = Sheets(1).Range("A1").End(xlDown).Row For ix1 = 1 To ix1_max - 1 For ix12 = ix1_max - 1 To ix1 Step -1 If Sheets(1).Cells(ix12, 1) > Sheets(1).Cells(ix12 + 1, 1) Then temp = Sheets(1).Cells(ix12, 1) Sheets(1).Cells(ix12, 1) = Sheets(1).Cells(ix12 + 1, 1) Sheets(1).Cells(ix12 + 1, 1) = temp End If Next Next
最終行である10行目と上の9行目の値を比較し、10行目の値が小さければ入替ます。
そして、9行目の値と8行目の値、8行目の値と7行目の値、・・・・と先頭1行目まで比較・入替えていくと、最も小さい値が1行目にセットされます。
再度、最終行である10行目から2行目まで、10行目から3行目まで、・・・後者'n行目まで'の[n]が最大行からマイナス1した行まで繰り返します。
最大行からマイナス1した行までにする意味は、選択ソートと同じです。
「泡のように下から浮き上がってくる」イメージのソートであることから'バブルソート' 日本語では'泡立ちソート'と言われます。
最後に
ソートにはいくつか種類があって比較回数が少ない処理もあります。
プログラミングを本格的にマスターする場合、言語を問わずテーブル=配列は避けて通れませんが、テーブルを使うことで処理を効率化できます。
業務でソート処理をプログラミングすることはないと思いますが、プログラミングの要である処理ロジックの技術を高める一助になればと思います。
コメント