Excel VBAでソートする方法をお探しですね。
広告
Excel VBAでデータを並べ替え(ソート)する!複数キーや昇順・降順の設定
Excelで名簿や売上表を扱っていると、「日付順に並べたい」「部署ごとにまとめたうえで金額の高い順にしたい」といった並べ替え作業がよく出てきますよね。
手作業でもソートはできますが、毎日同じ条件で並べ替えるならVBAで自動化したほうがラクで確実です。
この記事では、Excel VBAでデータを並べ替える方法を、基本の書き方から複数条件の指定、実務で失敗しやすいポイントまで分かりやすく解説していきます。
Excel VBAでデータを並べ替える基本
Excel VBAでデータを並べ替えるときは、主に`Range.Sort`メソッドか、ワークシートの`Sort`オブジェクトを使います。
「A列を昇順にする」「売上金額を降順にする」といったシンプルな処理なら、`Range.Sort`を使うと短いコードで済みます。
一方、複数の条件を指定したり、あとから条件を追加・変更したりする場合は、`SortFields`を使う書き方のほうが管理しやすくなります。
VBAでソートするときに大事なのは、次の4つをはっきりさせることです。
– どの範囲を並べ替えるか
– どの列を基準にするか
– 昇順か降順か
– 見出し行を含むか
たとえば、A1からE100までの表があって、1行目が見出し、A列の日付を古い順に並べたい場合は、こんなふうに書けます。
“`vba
Sub SortByDateAscending()
Range(“A1:E100”).Sort _
Key1:=Range(“A1”), _
Order1:=xlAscending, _
Header:=xlYes
End Sub
“`
`Key1`には並べ替えの基準となる列、`Order1`には昇順か降順か、`Header`には見出し行があるかどうかを指定します。
`xlAscending`は昇順、`xlDescending`は降順です。
日付や数値なら小さい値から大きい値へ、文字列なら五十音順やアルファベット順に近い並びになります。
このコードでは、A1:E100の表全体がA列を基準に並べ替えられます。
ここで大切なのは、**A列だけを並べ替えるのではなく、表全体の行が連動して移動する**という点です。
もしA列だけを選択してソートしてしまうと、氏名や金額など他の列との対応関係がバラバラになってしまいます。
VBAでソートを行うときは、必ず「表全体の範囲」を指定するよう意識しましょう。
また、見出し行がある表では`Header:=xlYes`を指定することで、見出しまでデータとして並べ替えられてしまう事故を防げます。
昇順・降順をVBAで指定する方法
昇順と降順の設定は、Excel VBAのソートで最も基本的なポイントです。
– **昇順**:小さい順、古い順、AからZ、あからんの方向に並べる → VBAでは`xlAscending`
– **降順**:大きい順、新しい順、ZからA、んからあの方向に並べる → VBAでは`xlDescending`
売上表なら「売上金額の高い順」は降順、入社日や注文日を時系列で見たいときは昇順を使うことが多いですね。
目的に合わせて切り替えるだけで、同じ表から違う見え方の資料が作れます。
たとえば、E列に売上金額が入っていて、金額が大きい順に並べたい場合は、`Order1:=xlDescending`を指定します。
“`vba
Sub SortBySalesDescending()
Range(“A1:E100”).Sort _
Key1:=Range(“E1”), _
Order1:=xlDescending, _
Header:=xlYes
End Sub
“`
基準にするセルは見出しセルでもデータ行の先頭セルでも動くことが多いですが、見出し付きの表では見出しセルを指定して`Header:=xlYes`を明示しておくと、あとで見返したときに分かりやすくなります。
データ件数が変わる表に対応する
実務では、固定範囲の`A1:E100`ではなく、データ件数が毎回変わることも多いですよね。
その場合は、最終行を取得してから範囲を指定すると便利です。
次の例では、A列を基準に最終行を求めて、A1からE列の最終行までをソート対象にしています。
“`vba
Sub SortDynamicRangeBySales()
Dim ws As Worksheet
Dim lastRow As Long
Set ws = Worksheets(“Sheet1”)
lastRow = ws.Cells(ws.Rows.Count, “A”).End(xlUp).Row
ws.Range(“A1:E” & lastRow).Sort _
Key1:=ws.Range(“E1”), _
Order1:=xlDescending, _
Header:=xlYes
End Sub
“`
データ追加のたびにコードを書き換える必要がなくなるので、日次レポートや受注一覧の整形など、繰り返し処理に向いています。
昇順・降順の切り替え自体は難しくないのですが、注意点もあります。
日付が文字列として入力されていたり、数値に見えるデータが文字列になっていたり、空白行が途中にあったりすると、期待どおりに並ばないことがあります。
VBAのコードだけで解決しようとする前に、**対象データの形式がそろっているか**を確認することも大切です。
特に外部システムからCSVを取り込んだ表では、数値や日付が文字列扱いになっていることがあるので注意しましょう。
複数キーで並べ替えるVBAコード
複数キーの並べ替えとは、「まず部署順に並べて、同じ部署の中では売上金額の高い順にする」といったように、優先順位を付けてソートする方法です。
Excelの画面操作では「並べ替え」ダイアログの「レベルの追加」で行う処理ですね。
VBAでも同じ考え方で、最優先のキー、次に優先されるキー、その次のキーという順番で条件を指定します。
単純な2条件くらいなら`Range.Sort`でも書けますが、実務で拡張しやすいのは`SortFields`を使う方法です。
次の例では、B列の部署を昇順、E列の売上金額を降順で並べ替えます。
つまり、部署ごとにまとまった状態にしたうえで、同じ部署内では売上の大きいデータが上に表示されます。
“`vba
Sub SortByDepartmentAndSales()
Dim ws As Worksheet
Dim lastRow As Long
Set ws = Worksheets(“Sheet1”)
lastRow = ws.Cells(ws.Rows.Count, “A”).End(xlUp).Row
With ws.Sort
.SortFields.Clear
.SortFields.Add Key:=ws.Range(“B2:B” & lastRow), _
SortOn:=xlSortOnValues, _
Order:=xlAscending, _
DataOption:=xlSortNormal
.SortFields.Add Key:=ws.Range(“E2:E” & lastRow), _
SortOn:=xlSortOnValues, _
Order:=xlDescending, _
DataOption:=xlSortNormal
.SetRange ws.Range(“A1:E” & lastRow)
.Header = xlYes
.Apply
End With
End Sub
“`
`SortFields.Clear`で既存の並べ替え条件をクリアして、`SortFields.Add`で条件を順番に追加していくのが基本の流れです。
最後に`SetRange`でソート対象範囲を指定し、`Header`で見出しの有無を指定してから`Apply`で実行します。
複数キーの優先順位に注意
複数キーを指定するときに意識したいのは、**条件を追加する順番**です。
最初に追加したキーが最優先され、次に追加したキーは「最優先キーの値が同じだった場合」に使われます。
上の例では、部署が違うデータ同士は売上金額ではなく部署名によって並びが決まり、同じ部署内に入ったデータだけが売上金額の降順で並びます。
この仕組みを理解しておくと、「日付順に並べて、同じ日付なら担当者順、同じ担当者なら金額順」といった複雑なソートも組み立てやすくなります。
3つ以上のキーを指定する
3つ以上のキーを指定したい場合も、考え方は同じです。
たとえば「注文日を昇順、担当者を昇順、売上を降順」にしたいなら、`SortFields.Add`を3回書きます。
“`vba
Sub SortByThreeKeys()
Dim ws As Worksheet
Dim lastRow As Long
Set ws = Worksheets(“Sheet1”)
lastRow = ws.Cells(ws.Rows.Count, “A”).End(xlUp).Row
With ws.Sort
.SortFields.Clear
.SortFields.Add Key:=ws.Range(“A2:A” & lastRow), Order:=xlAscending
.SortFields.Add Key:=ws.Range(“C2:C” & lastRow), Order:=xlAscending
.SortFields.Add Key:=ws.Range(“E2:E” & lastRow), Order:=xlDescending
.SetRange ws.Range(“A1:E” & lastRow)
.Header = xlYes
.Apply
End With
End Sub
“`
画面操作のソートでも複数条件を追加できますが、VBAで書いておけば毎回同じ条件を再現できるため、担当者による操作ミスを減らせます。
特に月次集計や管理表の整形では、ソート条件が少し違うだけで集計結果の確認効率が落ちることがあるので、自動化の効果が大きい部分です。
ユーザー独自の順番で並べたい場合
なお、ユーザー独自の順番で並べ替えたい場合は、単純な昇順・降順だけでは対応できません。
たとえば「東京支店、大阪支店、名古屋支店」の順にしたい場合や、「高、中、低」の順に優先度を並べたい場合です。
このようなケースでは、**補助列を作って並び順を数値化してからソートする**方法が安定します。
VBAでユーザー設定リストを利用する方法もありますが、保守性を考えると、別シートに順番マスタを用意して番号を付ける設計のほうが、あとから変更しやすくて実務向きです。
VBAソートで失敗しないための注意点と実務のコツ
VBAでソートを自動化すると便利ですが、範囲指定やデータ状態を間違えると、表の整合性が崩れることがあります。
特に多い失敗は、**並べ替え対象の範囲が一部の列だけになってしまい、氏名と売上、日付と担当者などの組み合わせがずれる**ケースです。
Excelのソートは行単位で動かすのが基本なので、基準列だけでなく、関連する列を含めた表全体を`SetRange`や`Range.Sort`で指定する必要があります。
コードを書く前に、どこからどこまでが1つの表なのかを確認しておきましょう。
見出し行の扱いに注意
また、見出し行の扱いも重要です。
`Header:=xlYes`または`.Header = xlYes`を指定しないと、Excel側が見出しの有無を自動判断することがあります。
自動判断に任せると、表の形式によっては見出し行まで並べ替え対象になり、項目名がデータの中に混ざってしまう可能性があります。
業務用のマクロでは、見出しがあるなら明示的に`xlYes`、見出しがないなら`xlNo`を指定するのが安全です。
コードの読みやすさも上がるので、あとから誰かがメンテナンスするときにも役立ちます。
VBAソート前に確認したい主なポイント
VBAソート前に確認したい主なポイントは、次のとおりです。
– 表の範囲に空白行や空白列が入り込んでいないか
– 結合セルが含まれていないか
– 日付や数値が文字列として保存されていないか
– 見出し行を含めるかどうかが明確になっているか
– 並べ替え前の順番に戻す必要があるか
結合セルはソート処理と相性が悪く、エラーや意図しない結果の原因になります。
見た目を整える目的で結合セルを使っている場合でも、データ表として扱う範囲ではできるだけ避けるのが基本です。
また、並べ替え前の状態に戻したい可能性がある場合は、あらかじめ「元順」などの連番列を作っておくと安心です。
ソート後に元へ戻したいときは、その連番列を昇順で並べ替えるだけで初期状態を再現できます。
これは手作業のExcel操作でもVBAでも使える実務テクニックです。
フィルターとソートを併用する場合
さらに、フィルターとソートを併用しているブックでは、表示されているデータだけを扱いたいのか、非表示行を含めた全体を並べ替えたいのかを明確にする必要があります。
通常のソートは表全体の並び順に影響しますが、フィルターで絞り込んだ状態だと、利用者が「見えている行だけが変わった」と誤解することがあります。
マクロ実行前にフィルターを解除する、処理後に再設定する、対象シートを限定するなど、運用に合わせた設計をしておくとトラブルを防げます。
テスト用シートで動作確認してから本番適用
最後に、VBAでソート処理を作るときは、**いきなり本番データで実行しない**ことも大切です。
テスト用のコピーシートを作って、意図どおりに行単位で並べ替わっているか、見出しが残っているか、複数キーの優先順位が正しいかを確認してから本番に適用しましょう。
Excel VBAのソートは、基本構文を覚えるだけなら難しくありません。
でも、実務で安心して使うには、範囲指定・見出し・データ形式・元に戻す方法まで含めて設計することが重要です。
ここまで押さえておけば、日々の並べ替え作業を安定して自動化できます。
ぜひ試してみてください。
広告
