Contents
この記事でできること
- VBAで単一条件(1列)のデータ並び替えを自動化できる
- 複数条件(部門→日付→金額など3つ)での並び替えをボタン1つで実行できる
- セルの背景色で並び替える方法も分かる
- 確認ダイアログ付きで安全にソートを実行できる
対象: Excel 2016以降 / Microsoft 365、Windows 10/11
完成イメージ(Before / After)
Before(手動ソート):
- データ範囲を選択
- 「データ」タブ →「並べ替え」をクリック
- 条件1(部門・昇順)を設定
- 「レベルの追加」→ 条件2(日付・降順)を設定
- 「レベルの追加」→ 条件3(金額・降順)を設定
- 「OK」で実行
- 毎回この5ステップを繰り返す
After(自動ソート):
- ボタンを押す(またはマクロを実行)
- 確認ダイアログが表示される → 「はい」をクリック
- 3つの条件で自動的に並び替え完了(3秒)
売上データを部門→金額の順で並び替えるのを毎日やっていた。ソートの条件を毎回手で設定するのが地味にストレスだった。VBAで自動化してからはボタン1つで3秒。毎日の並び替え作業から解放されたい人に、この記事で同じ快適さを手に入れてほしい。
データの並び替えは、VBAに任せれば毎回の手動設定が不要になる。
実行前の準備
バックアップを取る
ソートはデータの行順を変更する操作。元に戻せない場合があるため、マクロ実行前にExcelファイルのコピーを別フォルダに保存しておく。
Excelをマクロ有効ブック(.xlsm)で保存する
拡張子が .xlsx のままだとマクロが保存できない。
- 「ファイル」→「名前を付けて保存」
- ファイルの種類を「Excelマクロ有効ブック (*.xlsm)」に変更
- 保存
手順(コピペ → 実行まで約5分)
VBE(コードを書く画面)を開く
- Excelで
Alt + F11を押す - VBE(Visual Basic Editor)が開く
標準モジュールを挿入する
- VBEのメニュー →「挿入」→「標準モジュール」
- 白い画面(コードウィンドウ)が表示される
コードを貼り付けて実行する
- コードウィンドウに、下のコードをそのままコピペする
Alt + F8→ マクロ名を選んで「実行」
ボタンに割り当てれば毎回Alt+F8を押さなくて済む。方法は マクロをボタン1つで実行する方法 を参照。
コード(最小版)– 単一条件で並び替え
まずは1つの列だけで並び替える最小コード。最終行の取得には Cells(Rows.Count, 1).End(xlUp).Row を使う。詳しくは 最終行を正確に取得する方法 を参照。
'============================================================
' ■ 単一条件でデータを並び替え(最小版)
' → A列を昇順で並び替え
'============================================================
Sub データを並び替える()
Dim ws As Worksheet
Dim lastRow As Long
Set ws = ActiveSheet
lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
' ソート条件をクリア(前回の条件が残るのを防止)
ws.Sort.SortFields.Clear
' A列を昇順で並び替え
ws.Sort.SortFields.Add2 _
Key:=ws.Range("A2:A" & lastRow), _
Order:=xlAscending
With ws.Sort
.SetRange ws.Range("A1:D" & lastRow)
.Header = xlYes
.Apply
End With
MsgBox "並び替えが完了しました。"
End Sub
書き換えポイント
| 変数・箇所 | 説明 | 初期値 |
|---|---|---|
Range("A2:A" & lastRow) |
ソート基準の列。B列にしたければ "B2:B" に変更 |
A列 |
xlAscending |
ソート順。降順なら xlDescending に変更 |
昇順 |
Range("A1:D" & lastRow) |
ソート対象の範囲。列数に応じて "A1:F" などに変更 |
A〜D列 |
コードの流れ
ActiveSheetで現在のシートを取得Cells(Rows.Count, 1).End(xlUp).RowでA列の最終行を取得SortFields.Clearで前回のソート条件をクリア(重要)SortFields.Add2でソート条件を追加(A列・昇順).SetRangeでソート対象範囲を指定し、.Header = xlYesでヘッダーを除外.Applyでソートを実行
コード(実務版)– 複数条件(3つ)で並び替え + 確認ダイアログ
実務では「部門→日付→金額」のように複数条件で並び替えることが多い。この実務版では、確認ダイアログで件数と条件を表示してから実行する。
自分はこのコードを毎日の売上レポートに使っている。部門別→日付の新しい順→金額の大きい順で並ぶので、報告書がそのまま完成する。ScreenUpdating = False で画面のちらつきも抑えている。画面ちらつき防止の詳細は 処理の高速化テクニック を参照。
確認ダイアログには MsgBoxの使い方 で紹介しているYes/Noダイアログを使っている。
マクロ実行中にエラーが発生すると、
ScreenUpdating = Falseのまま画面更新が停止した状態になることがある。その場合はVBEの「イミディエイトウィンドウ」でApplication.ScreenUpdating = Trueを実行すれば復帰する。
'============================================================
' ■ 複数条件(3つ)でデータを並び替え(実務版)
' → 条件1: A列(部門)昇順
' → 条件2: B列(日付)降順
' → 条件3: C列(金額)降順
' → 実行前に確認ダイアログを表示
'============================================================
Sub 複数条件で並び替える()
Dim ws As Worksheet
Dim lastRow As Long
Set ws = ActiveSheet
lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
'--- データがない場合は終了
If lastRow < 2 Then
MsgBox "データがありません。", vbExclamation
Exit Sub
End If
'--- 確認ダイアログ(件数と条件を表示)
If MsgBox((lastRow - 1) & " 件のデータを並び替えます。" & vbCrLf & _
"条件: 部門(昇順) → 日付(降順) → 金額(降順)" & vbCrLf & vbCrLf & _
"実行しますか?", vbYesNo + vbQuestion) = vbNo Then
Exit Sub
End If
'--- 画面更新を停止(高速化)
Application.ScreenUpdating = False
'--- ソート条件をクリア(★これを忘れると前回の条件が残る)
ws.Sort.SortFields.Clear
'--- 条件1:A列(部門)を昇順
ws.Sort.SortFields.Add2 _
Key:=ws.Range("A2:A" & lastRow), _
Order:=xlAscending
'--- 条件2:B列(日付)を降順
ws.Sort.SortFields.Add2 _
Key:=ws.Range("B2:B" & lastRow), _
Order:=xlDescending
'--- 条件3:C列(金額)を降順
ws.Sort.SortFields.Add2 _
Key:=ws.Range("C2:C" & lastRow), _
Order:=xlDescending
'--- ソート実行
With ws.Sort
.SetRange ws.Range("A1:D" & lastRow)
.Header = xlYes
.MatchCase = False
.Apply
End With
'--- 画面更新を再開
Application.ScreenUpdating = True
MsgBox "並び替えが完了しました。"
End Sub
書き換えポイント
| 変数・箇所 | 説明 | 初期値 |
|---|---|---|
Range("A2:A" & lastRow) |
条件1の対象列 | A列(部門) |
Range("B2:B" & lastRow) |
条件2の対象列 | B列(日付) |
Range("C2:C" & lastRow) |
条件3の対象列 | C列(金額) |
xlAscending / xlDescending |
各条件のソート順 | 部門:昇順、日付:降順、金額:降順 |
Range("A1:D" & lastRow) |
ソート対象の全範囲。列が多ければ "A1:H" などに変更 |
A〜D列 |
コードの流れ
- データ存在チェック: 最終行が2未満ならデータなしで終了
- 確認ダイアログ: 件数とソート条件を表示し、「いいえ」なら中止
- 画面更新を停止:
ScreenUpdating = Falseでちらつきを防止 - SortFields.Clear: 前回のソート条件をクリア(これを忘れると大事故)
- 条件を追加:
Add2を3回呼び出し、優先度順に条件を設定 - ソート実行:
.SetRangeで範囲指定、.Header = xlYesでヘッダー除外、.Applyで実行 - 画面更新を再開:
ScreenUpdating = True
SortFields.Add2は呼び出した順が優先度になる。最初に追加した条件が第1ソートキー。
応用:色(セルの背景色)で並び替え
セルの背景色で並び替えたい場面もある。たとえば「赤色のセルを先頭に持ってくる」という使い方。
セルに設定した色のRGB値を確認するには、セルを右クリック →「セルの書式設定」→「塗りつぶし」→「その他の色」→「ユーザー設定」タブで赤・緑・青の値を確認する。コード内の
RGB()にはこの値を指定する。値が一致しないとソートされないため注意。
'============================================================
' ■ セルの背景色で並び替え(応用)
' → 赤色(RGB 255,0,0)のセルを先頭に並べる
'============================================================
Sub 色で並び替える()
Dim ws As Worksheet
Dim lastRow As Long
Set ws = ActiveSheet
lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
ws.Sort.SortFields.Clear
ws.Sort.SortFields.Add2 _
Key:=ws.Range("A2:A" & lastRow), _
SortOn:=xlSortOnCellColor, _
Order:=xlAscending, _
DataOption:=xlSortNormal
ws.Sort.SortFields(ws.Sort.SortFields.Count).SortOnValue.Color = RGB(255, 0, 0)
With ws.Sort
.SetRange ws.Range("A1:D" & lastRow)
.Header = xlYes
.Apply
End With
MsgBox "色で並び替えました。"
End Sub
書き換えポイント
| 変数・箇所 | 説明 | 初期値 |
|---|---|---|
SortOn:=xlSortOnCellColor |
ソート基準を「セルの背景色」に設定 | 色ソート |
RGB(255, 0, 0) |
対象色。黄色なら RGB(255, 255, 0)、青なら RGB(0, 0, 255) |
赤 |
色ソートは「指定した色のセルを先頭に集める」動作。複数色で段階的に並べたい場合は、
SortFields.Add2を色ごとに複数回呼び出す。
よくある落とし穴5選
1. SortFields.Clear を忘れて前回の条件が残る
原因: SortFields.Clear を書かないと、前回実行時のソート条件が残ったまま新しい条件が追加される。意図しない並び順になる。
自分もこれでやらかした。SortFields.Clear を書き忘れて、前回の日付ソート条件が残ったまま実行。部門順で並べたつもりが日付順になっていて、提出した報告書が「並び順おかしくない?」と上司に指摘された。それ以来、Clearは必ず最初に書くようにしている。
対策: ソート条件を追加する前に、必ず ws.Sort.SortFields.Clear を実行する。
2. .Header = xlYes を忘れてヘッダーもソート対象になる
原因: .Header = xlYes を指定しないと、1行目のヘッダー(「部門」「日付」「金額」など)もデータとしてソートされる。ヘッダーが行の途中に混ざる。
対策: .Header = xlYes を必ず指定する。ヘッダーがない場合は .Header = xlNo を指定。
3. 結合セルがあるとソートエラーになる
原因: ソート範囲に結合セルが含まれていると、実行時にエラー(「この操作を行うには、すべての結合セルを同じサイズにする必要があります」)が出る。
対策: ソート前に結合を解除する。シート全体の結合を解除するなら ws.Cells.UnMerge を実行する。結合セルとソートは相性が悪いため、データ範囲では結合を使わないのが基本。
4. 日付が文字列として保存されていると並び順がおかしい
原因: セルに入力された日付が「日付型」ではなく「文字列」として保存されている場合、ソートすると「10月」が「1月」の後ではなく「2月」の前に来る(文字列の辞書順で比較されるため)。
見分け方: セルを選択して右クリック →「セルの書式設定」→「表示形式」タブで分類が「文字列」になっていたら、日付型への変換が必要。
対策: 日付列を選択 →「データ」→「区切り位置」→ 列のデータ形式で「日付」を選択。これでセルの値が日付型に変換される。VBAで変換するなら CDate(セル.Value) を使う。
5. ソート範囲に空白列があると範囲がズレる
原因: データの途中に空白列があると、Excelが自動認識する範囲が空白列の手前で切れてしまう。結果、一部の列だけがソートされてデータの対応がずれる。
対策: .SetRange でソート範囲を明示的に指定する。このコードでは ws.Range("A1:D" & lastRow) と範囲を明示しているため、空白列があっても問題ない。自動認識に頼らず、必ず SetRange を使う。
FAQ
Q1: 降順で並び替えたい場合は?
Order:=xlAscending を Order:=xlDescending に変更する。
ws.Sort.SortFields.Add2 _
Key:=ws.Range("A2:A" & lastRow), _
Order:=xlDescending ' ← 降順
Q2: ソート対象の列を変えたい(B列やC列で並び替えたい)
Key の Range を変更する。B列なら "B2:B" & lastRow、C列なら "C2:C" & lastRow。
ws.Sort.SortFields.Add2 _
Key:=ws.Range("B2:B" & lastRow), _ ' ← B列に変更
Order:=xlAscending
Q3: ソート後に元の順番に戻したい
ソートは行の並び順を直接変更するため、元に戻す機能(Undo)は使えない。事前に連番のID列を追加しておき、戻すときはID列でソートする。
' 事前にE列に連番を振っておく
Dim i As Long
For i = 2 To lastRow
ws.Cells(i, 5).Value = i - 1 ' E列に連番
Next i
Q4: ボタンに割り当てて実行したい
手順セクションで紹介した「マクロをボタン1つで実行する方法」の手順でシート上にボタンを設置し、このマクロを割り当てる。自分はこの方法で並び替えマクロをボタンに割り当てて、チームメンバーにも使ってもらっている。
Q5: ソート後に重複データを削除したい
並び替え後の重複削除は 重複データを一括削除して一意のリストを作る を参照。ソートで同じ値を隣接させてから重複削除すると、結果の確認がしやすい。
まとめ
SortFields.Clear→SortFields.Add2→.ApplyがVBAソートの基本の流れ- 複数条件は
Add2を複数回呼び出すだけ。呼び出し順が優先度になる .Header = xlYesを忘れるとヘッダーもソート対象になるSortFields.Clearを忘れると前回の条件が残る。これが最大の落とし穴
関連記事
- 処理の高速化テクニック — ScreenUpdating以外にも使える高速化の手法
- MsgBoxの使い方 — 確認ダイアログや通知メッセージのバリエーション
- 最終行を正確に取得する方法 — Cells.End(xlUp).Row の詳細解説
次にやりたくなること
- 重複データを一括削除して一意のリストを作る: ソート後に重複を削除してユニークリストを作る。並び替えと重複削除はセットで使うことが多い
- 複数条件でデータを抽出して別シートにまとめる: ソート後に特定条件のデータだけを抽出して別シートにまとめる。報告書作成の定番フロー
もっとカスタマイズしたい場合
「部門ごとに小計行を自動挿入したい」「ソート→抽出→PDF出力を一連で自動化したい」「複数シートを一括でソートしたい」など、業務に合わせたカスタマイズが必要な場合は、ココナラで相談できる。
相談時に伝えると話が早い情報:
- Excel のバージョン / OS
- ソート対象のデータ構成(列名、行数)
- ソート条件(何列目を昇順/降順にしたいか)
- ソート後にやりたい処理(抽出、PDF出力など)

コメント