Excel VBA 逆引き集 | シートを並べ替える

Excel VBA
スポンサーリンク

シートを並べ替える

「名前順にソート」「任意の並びに並べ替え」「一部だけ並べ替え」まで、初心者が混乱しやすいポイントを避けて、確実に動くテンプレートと例題でまとめます。コツは「Moveで位置を変える」「インデックスがずれない順番で動かす」ことです。


基本:Moveで位置を変える(最短パターン)

Sub MoveSheet_Basic()
    '「売上」を左端へ
    ThisWorkbook.Worksheets("売上").Move Before:=ThisWorkbook.Worksheets(1)

    '「在庫」を右端へ
    ThisWorkbook.Worksheets("在庫").Move After:=ThisWorkbook.Worksheets(ThisWorkbook.Worksheets.Count)
End Sub
VB
  • ポイント:
    • 位置指定: Before/After はどちらか一方のみ指定。1は左端、Worksheets.Countは右端。
    • 対象明示: ThisWorkbookで「このブック」を対象に。ActiveWorkbookと混同しない。

名前順に並べ替える(昇順・降順)

Sub SortSheetsByName(Optional ascending As Boolean = True)
    Dim names() As String
    Dim i As Long, j As Long, n As Long, tmp As String

    n = ThisWorkbook.Worksheets.Count
    If n <= 1 Then Exit Sub

    'シート名を配列へ
    ReDim names(1 To n)
    For i = 1 To n
        names(i) = ThisWorkbook.Worksheets(i).Name
    Next

    '単純バブルソート(初心者向け)
    For i = 1 To n
        For j = i + 1 To n
            If ascending Then
                If StrComp(names(i), names(j), vbTextCompare) > 0 Then
                    tmp = names(i): names(i) = names(j): names(j) = tmp
                End If
            Else
                If StrComp(names(i), names(j), vbTextCompare) < 0 Then
                    tmp = names(i): names(i) = names(j): names(j) = tmp
                End If
            End If
        Next j
    Next i

    '並べ替えた順に移動(左から順に並べる)
    Application.ScreenUpdating = False
    ThisWorkbook.Worksheets(names(1)).Move Before:=ThisWorkbook.Worksheets(1)
    For i = 2 To n
        ThisWorkbook.Worksheets(names(i)).Move After:=ThisWorkbook.Worksheets(i - 1)
    Next
    Application.ScreenUpdating = True
End Sub

Sub Example_SortAsc()
    SortSheetsByName True  '昇順
End Sub

Sub Example_SortDesc()
    SortSheetsByName False '降順
End Sub
VB
  • ポイント:
    • 大小無視: vbTextCompareで大文字小文字を無視。
    • 再配置: 「左端へ先頭を置いて、以降はその直後へ」並べるとインデックスが安定。

任意の順番に並べ替える(配列・一覧シート)

配列で順番を指定

Sub ReorderByArray(order As Variant)
    Dim i As Long, target As String, pos As Long

    Application.ScreenUpdating = False

    '1番目から順に並べる(存在しない名前はスキップ)
    For i = LBound(order) To UBound(order)
        target = CStr(order(i))
        If SheetExists(target) Then
            If i = LBound(order) Then
                ThisWorkbook.Worksheets(target).Move Before:=ThisWorkbook.Worksheets(1)
            Else
                '現在の並びの i 番目の直後に置く
                pos = i - LBound(order) + 1
                ThisWorkbook.Worksheets(target).Move After:=ThisWorkbook.Worksheets(pos - 1)
            End If
        End If
    Next

    Application.ScreenUpdating = True
End Sub

Function SheetExists(name As String) As Boolean
    Dim t As Worksheet
    On Error Resume Next
    Set t = ThisWorkbook.Worksheets(name)
    SheetExists = Not t Is Nothing
    On Error GoTo 0
End Function

Sub Example_ReorderArray()
    Dim order As Variant
    order = Array("トップ", "売上", "在庫", "顧客", "設定")
    ReorderByArray order
End Sub
VB
  • ポイント:
    • 柔軟: 欲しい並びをそのまま書ける。存在しない名前は安全にスキップ。
    • 前から詰める: 左端→以降直後に置くと意図通りに並ぶ。

一覧シート(Control!A列)で指定

Sub ReorderByControlList()
    Dim ctrl As Worksheet, last As Long, r As Long, name As String, idx As Long

    Set ctrl = ThisWorkbook.Worksheets("Control")
    last = ctrl.Cells(ctrl.Rows.Count, "A").End(xlUp).Row
    If last < 2 Then Exit Sub

    Application.ScreenUpdating = False

    'A2から順に並べる
    idx = 1
    For r = 2 To last
        name = CStr(ctrl.Cells(r, "A").Value)
        If SheetExists(name) Then
            If idx = 1 Then
                ThisWorkbook.Worksheets(name).Move Before:=ThisWorkbook.Worksheets(1)
            Else
                ThisWorkbook.Worksheets(name).Move After:=ThisWorkbook.Worksheets(idx - 1)
            End If
            idx = idx + 1
        End If
    Next

    Application.ScreenUpdating = True
End Sub
VB
  • ポイント:
    • 運用に強い: 並びを表で管理でき、編集もしやすい。

一部だけ並べ替える(可視限定・除外あり)

Sub SortVisibleWorksheetsByName()
    Dim vis() As String, ws As Worksheet, n As Long, i As Long, j As Long, t As String

    '可視ワークシート名を配列化
    For Each ws In ThisWorkbook.Worksheets
        If ws.Visible = xlSheetVisible Then
            n = n + 1
            ReDim Preserve vis(1 To n)
            vis(n) = ws.Name
        End If
    Next
    If n <= 1 Then Exit Sub

    '昇順にソート
    For i = 1 To n
        For j = i + 1 To n
            If StrComp(vis(i), vis(j), vbTextCompare) > 0 Then
                t = vis(i): vis(i) = vis(j): vis(j) = t
            End If
        Next j
    Next i

    '可視シートだけ前詰めで再配置(非表示は触らない)
    Application.ScreenUpdating = False
    ThisWorkbook.Worksheets(vis(1)).Move Before:=ThisWorkbook.Worksheets(1)
    For i = 2 To n
        ThisWorkbook.Worksheets(vis(i)).Move After:=ThisWorkbook.Worksheets(i - 1)
    Next
    Application.ScreenUpdating = True
End Sub
VB
  • ポイント:
    • 非表示を保つ: VeryHidden/Hiddenを動かしたくないときに有効。
    • 画面安定: 先頭から順に並べると意図通りになる。

例題で練習

例題1:月次レポートを「トップ→設定→月次→その他」の順に並べる

Sub Example_MonthlyOrder()
    Dim order As Variant
    order = Array("トップ", "設定", "月次", "その他")
    ReorderByArray order
End Sub
VB
  • ポイント:
    • 明確な順序: 重要シートを前に、補助系を後ろへ。

例題2:名前の先頭が「週報_」のシートだけを名前順で前方に集約

Sub Example_CollectWeeklyToFront()
    Dim ws As Worksheet, list As New Collection, i As Long

    '対象を収集
    For Each ws In ThisWorkbook.Worksheets
        If Left$(ws.Name, 3) = "週報" Then list.Add ws.Name
    Next
    If list.Count = 0 Then Exit Sub

    '前方へ固める(順序は収集順、必要なら名前ソートを挟む)
    Application.ScreenUpdating = False
    ThisWorkbook.Worksheets(list(1)).Move Before:=ThisWorkbook.Worksheets(1)
    For i = 2 To list.Count
        ThisWorkbook.Worksheets(list(i)).Move After:=ThisWorkbook.Worksheets(i - 1)
    Next
    Application.ScreenUpdating = True
End Sub
VB
  • ポイント:
    • 集約: 週報など系列シートを前方にまとめて見やすく。

例題3:目次(Index)の次に「売上」「在庫」「顧客」を並べ替え

Sub Example_AfterIndexOrder()
    Dim anchorPos As Long, order As Variant, i As Long

    'Indexの位置を特定
    anchorPos = ThisWorkbook.Worksheets("Index").Index

    Application.ScreenUpdating = False

    order = Array("売上", "在庫", "顧客")
    For i = LBound(order) To UBound(order)
        If SheetExists(CStr(order(i))) Then
            ThisWorkbook.Worksheets(CStr(order(i))).Move After:=ThisWorkbook.Worksheets(anchorPos)
            anchorPos = ThisWorkbook.Worksheets(CStr(order(i))).Index
        End If
    Next

    Application.ScreenUpdating = True
End Sub
VB
  • ポイント:
    • アンカーを使う: 指定シートの直後に連続で並べると、束で扱いやすい。

実務の落とし穴と対策

  • インデックスのズレ:
    • 対策: 左端から順に「先頭→直後」方式で並べる。削除・挿入と同様、逆順ループやアンカーを活用。
  • 存在しない名前:
    • 対策: 事前に存在チェック。上の SheetExists 関数を必ず使う。
  • 非表示/VeryHiddenの扱い:
    • 対策: 可視限定で動かすか、動かす対象を明示的にリスト化。
  • ThisWorkbookとActiveWorkbookの混同:
    • 対策: 対象ブックを統一して記述。別ブックなら Workbooks(“名前”) を使って渡す。
  • 大量枚数のパフォーマンス:
    • 対策: Application.ScreenUpdating を False にしてからまとめて移動、最後に True に戻す。

タイトルとURLをコピーしました