Excel VBAでシートを移動する方法

今回の目標

「マクロでシートを移動したい!」や「安全にシートを移動するにはどうすれば良いの?」と思ったあなたへ。 この記事では、シートを移動する方法や、複数のシートを一度に移動する方法、別のブックにシートを移動する方法等を丁寧に解説します! 実務で使える具体例つきです。

目標リスト

  • シートを移動させられるようになる
  • 別のブックへシートを移動できるようになる
  • 新しいブックへシートを移動できるようになる
  • エラーを発生させずに、シートを移動できるようになる

説明

シートの移動について

Excelマクロでは、シートを移動できます。
シートを移動するとは、ブック内でシートの見出し(シートの下にあるシート名が書かれたタブのこと)の並び順を変えたり、他のブックへシートを切り取ることを言います。
マクロからシートの移動を行うこともでき、複数のシートを同時に移動、他のブックへ移動することができます。
シートの見出しについての画像

Worksheets("シート名").Move

シートを移動する場合、Worksheets オブジェクトの Move メソッドを使用します。 「Worksheets("シート名").Move」とシート名を指定するか、「Worksheets(1).Move」とインデックス番号でシートを指定する方法が可能です。

メソッドの構文

シートオブジェクト.Move(Before, After)

Move メソッドの引数一覧

引数省略説明
Before可能シートオブジェクトを指定する。指定したシートの1つ左に、シートを移動する。
After可能シートオブジェクトを指定する。指定したシートの1つ右に、シートを移動する。

Application.ScreenUpdating

「Application.ScreenUpdating」は、Excelの画面の更新を停止させることができます。
画面の更新を止めると、セルにデータを入力してもシート上の画面が変わりません。 主にマクロの高速化に使用しますが、今回は、画面のちらつきを防ぐために使用します。

移動先のシートが非表示の場合、シートの移動に失敗することがあります(この時、エラーはしません)。 そのため、移動先のシートを表示させる → シートを移動する → シートを表示状態を元に戻す、と処理を行います。
詳細は「移動先が非表示シートだと移動先がおかしくなる?」に続きます。

・Excelの画面を更新しない

Application.ScreenUpdating = False

・Excelの画面を更新する

Application.ScreenUpdating = True

ブック内のシートを移動する

シートを特定のシートの左隣へ移動する

シートを特定のシートの左隣へ移動する方法です。
サンプルコードでは、"Sheet1" を "Sheet3" の左隣りに移動します。

サンプルコード

Sub SampleSheetMove1_1()
    ' "Sheet1" を "Sheet3" の左隣りに移動する
    Worksheets("Sheet1").Move _
            before:=Worksheets("Sheet3")
End Sub
【実行サンプル】

● 実行前
プログラム実行前の画像

● 実行後
プログラム実行後の画像

シートを特定のシートの右隣へ移動する

シートを特定のシートの右隣へ移動する方法です。
サンプルコードでは、"Sheet1" を "Sheet3" の右隣りに移動します。

サンプルコード

Sub SampleSheetMove1_2()
    ' "Sheet1" を "Sheet3" の右隣りに移動する
    Worksheets("Sheet1").Move _
            after:=Worksheets("Sheet3")
End Sub
【実行サンプル】

● 実行前
プログラム実行前の画像

● 実行後
プログラム実行後の画像

シートを一番左(先頭)へ移動する

シートを一番左(先頭)へ移動する方法です。
「Worksheets(1)」と書くことで、ブックの一番左(先頭)のシートを指します。 サンプルコードでは、"Sheet3" を一番左(先頭)に移動します。

サンプルコード

Sub SampleSheetMove1_3()
    ' "Sheet3" を一番左(先頭)に移動する
    Worksheets("Sheet3").Move _
            before:=Worksheets(1)
End Sub
【実行サンプル】

● 実行前
プログラム実行前の画像

● 実行後
プログラム実行後の画像

シートを一番右(最後尾)へ移動する

シートを一番右(最後尾)へ移動する方法です。
「Worksheets.Count」は、ブックに存在するシートの枚数を返します。 「Worksheets(Worksheets.Count)」とすることで、最後尾のシートオブジェクトを指すことができます。 サンプルコードでは、"Sheet2" を一番右(最後尾)に移動します。

サンプルコード

Sub SampleSheetMove1_4()
    ' "Sheet2" を一番右(最後尾)に移動する
    Worksheets("Sheet2").Move _
            after:=Worksheets(Worksheets.Count)
End Sub
【実行サンプル】

● 実行前
プログラム実行前の画像

● 実行後
プログラム実行後の画像

複数のシートを移動する

複数のシートを移動する方法です。
「Worksheets(Array("Sheet1", "Sheet2"))」とすることで、"Sheet1" と "Sheet2" を指定できます。
サンプルコードでは、"Sheet1" と "Sheet2" を移動します。

サンプルコード

Sub SampleSheetMove1_5()
    ' "Sheet1" と "Sheet2" を一番右(最後尾)に移動する
    Worksheets(Array("Sheet1", "Sheet2")).Move _
        after:=Worksheets(Worksheets.Count)
End Sub
【実行サンプル】

● 実行前
プログラム実行前の画像

● 実行後
プログラム実行後の画像

移動先が非表示シートだと移動先がおかしくなる?

移動先に非表示シートを指定すると動作が期待通りにならない場合があります。
例えば、非表示のシートが一番左(先頭)にあるときに先頭へ移動する場合や、一番右(最後尾)のシートが非表示の時に最後尾へ移動する場合、この現象が発生します。

サンプルコードでは、一番右(最後尾)に非表示のシートがある状態で、 "Sheet1" を最後尾へ移動します。

サンプルコード

Sub SampleSheetMove1_6_1()
    Dim cnt As Long

    cnt = Worksheets.Count
    
    ' 最後尾(移動先)のシートを 非表示にする
    '  ※ 実行前に手動で非表示にしても同様の結果です
    Worksheets(cnt).Visible = xlSheetHidden
    
    ' "Sheet1" を最後尾に移動する
    '   ※ 再表示すると、最後尾に移動できていない
    Worksheets("Sheet1").Move _
            after:=Worksheets(cnt)
End Sub
【実行サンプル】

● 実行前
プログラム実行前の画像

● 実行後
プログラム実行後の画像(再表示前)

再表示をすると・・・
再表示画面

”Sheet1” が ”Sheet4” の左隣に移動されており、最後尾に移動できていない
プログラム実行後の画像(再表示後)

移動先が非表示なら、表示 → 移動 → 非表示 で対応!

移動先のシートが非表示の場合、次の手順で対応します。

 移動先のシートが非表示の場合

  1. 移動先のシートの表示/非表示の状態を取得する
  2. 移動先のシートを表示する
  3. シートの移動する
  4. 移動先のシートを元に戻す

移動先のシートが非表示の場合、次の手順で対応します。
シートの表示/非表示については、下記リンクにまとめています。
・リンク:シートの表示と非表示を切り替える方法

サンプルコード

Sub SampleSheetMove1_6_2()
    Dim visi As Long          ' 移動先の表示状態
    Dim posWs As Worksheet    ' 移動先のシートオブジェクト
    Dim cnt As Long
    
    cnt = Worksheets.Count
    ' 画面更新を行うか、取得する
    updating = Application.ScreenUpdating
    
    ' 最後尾(移動先)のシートオブジェクトを代入する
    Set posWs = Worksheets(cnt)
    ' 移動先のシートの表示状態を取得する
    visi = posWs.Visible
    ' 移動先のシートの表示を「表示する」へ変更する
    posWs.Visible = True
    '  "Sheet1" を 最後尾 に移動する
    Worksheets("Sheet1").Move after:=posWs
    
    ' 移動先のシートの表示状態を元に戻す
    posWs.Visible = visi
End Sub
【実行サンプル】

● 実行前
プログラム実行前の画像

● 実行後
プログラム実行前の画像

再表示をすると・・・
プログラム実行前の画像

"Sheet1" が最後尾に移動されている!
プログラム実行前の画像

他のブックへシートを移動する

新しいブックを作成してシートを移動する

新しいブックを作成してシートを移動する方法です。
移動後は、アクティブなブックが新しいブックになり、同時に移動先のシートがアクティブなシートになります。 実務では移動先のシートを操作することが多いため、それぞれを変数に代入しておくと便利です。

なお、シートオブジェクトを変数に代入した後に、シートを移動、その変数を参照するとエラーが発生します。 移動後にシートオブジェクトを変数へ代入してください。

サンプルコードでは、マクロを実行しているブックの "Sheet3" を新規ブックへ移動します。

サンプルコード

Sub SampleSheetMove2_1()
    Dim wb As Workbook
    Dim ws As Worksheet
    
    ' "Sheet3" を新規ブックに移動する
    Worksheets("Sheet3").Move
    
    Set wb = ActiveWorkbook
    Set ws = ActiveSheet
End Sub
【実行サンプル】

● 実行前
プログラム実行前の画像

● 実行後(新規ブックのシートの見出し)
プログラム実行後の画像

開いている他のブックにシートを移動する

開いている他のブックにシートを移動する方法です。
移動先のブックと 移動位置(After / Before)を指定します。 なお、コピー先となるブックをあらかじめ開いておく必要があります。

サンプルコードでは、マクロを実行しているブックの "Sheet3" を "Book1.xlsx" の "Sheet1" の右隣りへ移動します。

サンプルコード

Sub SampleSheetMove2_2()
    ' マクロを実行しているブックの "Sheet3" を _
       "Book1.xlsx" の "Sheet1" の右隣りへ移動する
    ThisWorkbook.Worksheets("Sheet3").Move _
        after:=Workbooks("Book1.xlsx").Worksheets("Sheet1")
End Sub
【実行サンプル】

● 実行前
プログラム実行前の画像

● 実行後
プログラム実行後の画像

● 実行後(同名のシート名があった場合" (2)"となる)
プログラム実行後の画像

安全にシートを移動する

移動できるか確認してから、シートを移動する

シートを安全に移動するには、次の項目の確認が必要です。

  • 移動のシートは存在するか
  • 移動のシートは存在するか
  • 移動のブックに「ブックの保護」が設定されていないか
  • 移動のブックに「ブックの保護」が設定されていないか
  • 移動のブックの表示シートが1枚の時、そのシートが移動対象か

サンプルコードでは、上記のチェックをそれぞれ関数化して、真偽を確認しています。 シートを移動できなかったとき、理由をメッセージボックスに表示します。

サンプルコード

Sub SampleSheetMove3_1()
    
    If MoveWorksheet(ThisWorkbook, "Sheet1", _
            ThisWorkbook, "Sheet22", True) Then
        ' シート移動できた時の処理
    
    Else
        ' シートを移動できなかった時の処理
    
    End If
End Sub

' --------------------------------------------------------------
' シートを移動できるか確認してから移動する
'     ※ 移動できない場合はメッセージボックスを表示する
'   srcWbObj  :移動元のブックオブジェクト
'   srcWsName :移動元のシート名
'   destWbObj :移動先のブックオブジェクト
'   destWsName:移動先のシート名
'   IsBefore :True/シート前へ移動、
'              False/シート後ろへ移動
'   戻り値:True /シートを移動できた
'       False/シートを移動できなかった
'--------------------------------------------------------------
Function MoveWorksheet(ByRef srcWbObj As Workbook, _
            ByRef srcWsName As String, _
            ByRef destWbObj As Workbook, _
            ByRef destWsName As String, _
            ByVal isBefore As Boolean) As Boolean

    On Error GoTo ErrHandler
    Dim flag1 As Boolean, flag2 As Boolean
    Dim flag3 As Boolean, flag4 As Boolean
    Dim flag5 As Boolean
    Dim errMsg As String
    Dim updating As Boolean
    Dim srcWsObj As Worksheet   ' 移動元のシートオブジェクト
    Dim destWsObj As Worksheet  ' 移動先のシートオブジェクト
    Dim destVisi As Long        ' 移動先の表示状態

    updating = Application.ScreenUpdating
    
    ' 移動元のシートが存在するか
    If IsSheetNameUsed(srcWbObj, srcWsName) Then
        flag1 = True
        Set srcWsObj = srcWbObj.Worksheets(srcWsName)
    End If
    ' 移動先のシートが存在するか
    If IsSheetNameUsed(destWbObj, destWsName) Then
        flag2 = True
        Set destWsObj = destWbObj.Worksheets(destWsName)
        destVisi = destWsObj.Visible
    End If
    
    ' 移動元/移動先に「ブックの保護」が掛けられていないか
    flag3 = IsUnProtectBook(srcWbObj)
    flag4 = IsUnProtectBook(destWbObj)
    
    ' 移動元ブックの表示状態のシートが1枚のとき、 _
        その表示状態のシートを他ブックへ移動するか?
    If srcWbObj Is destWbObj Then
        ' 移動元と移動先のブックが同じなら問題ない
        flag5 = True
    ElseIf flag1 Then
        flag5 = IsAllowedToMoveSheet(srcWbObj, srcWsName)
    End If
    
    ' 1つでも成立していないフラグがあると、シートを移動できない
    If Not (flag1 And flag2 And flag3 And flag4 And flag5) Then
        ' エラーメッセージの生成1
        errMsg = "エラーが発生しました。" & vbNewLine & _
            "この画面をキャプチャして、" & vbNewLine & _
            "システム管理者にご連絡ください。" & vbNewLine & _
            "ーーーーーーーーーーーーーーーー" & vbNewLine & _
            "シートを移動できませんでした。" & vbNewLine & _
            "● 移動元情報" & vbNewLine & _
            " ・ブック名:" & srcWbObj.name & vbNewLine & _
            " ・シート名:" & srcWsName & vbNewLine & _
            "● 移動先情報" & vbNewLine & _
            " ・ブック名:" & destWbObj.name & vbNewLine & _
            " ・シート名:" & destWsName & vbNewLine & _
            "● 移動できなかった原因"

        If Not flag1 Then errMsg = errMsg & vbNewLine & _
            " ・移動元のシート名[" & srcWsName & "]がありません"
        If Not flag2 Then errMsg = errMsg & vbNewLine & _
            " ・移動先のシート名[" & destWsName & "]がありません"
        If Not flag3 Then errMsg = errMsg & vbNewLine & _
            " ・移動元のブックの保護を解除してください"
        If Not flag4 Then errMsg = errMsg & vbNewLine & _
            " ・移動先のブックの保護を解除してください"
        If Not flag5 And flag1 Then errMsg = errMsg & vbNewLine & _
            " ・表示されているシートが1枚のとき、" & _
                "そのシートは移動できません"
    End If
    
    If errMsg = "" Then
        Application.ScreenUpdating = False
        destWsObj.Visible = xlSheetVisible
        If isBefore Then
            srcWsObj.Move before:=destWsObj
        Else
            srcWsObj.Move after:=destWsObj
        End If
        destWsObj.Visible = destVisi
        MoveWorksheet = True
    Else
        MsgBox errMsg, vbCritical
        MoveWorksheet = False
    End If
    
CleanUp:
    On Error Resume Next
    Application.ScreenUpdating = updating
    If Not destWsObj Is Nothing Then
        destWsObj.Visible = destVisi
    End If
    On Error GoTo 0
    Exit Function
    
ErrHandler:
    ' エラー時の処理
    
    ' お掃除
    Resume CleanUp
End Function

' --------------------------------------------------------------
' ブックに同名のシート名が存在しているか確認する
'   wb   :確認対象のブックオブジェクト
'   srcWs:移動したいシート名
'   戻り値:True/同名のシート名が存在している
'--------------------------------------------------------------
Function IsSheetNameUsed(ByRef wb As Workbook, _
            ByRef srcWsName As String) As Boolean
    Dim buf As Worksheet
    
    ' ブックを1シートずつ、名前が一致している確認する
    For Each buf In wb.Worksheets
        If buf.name = srcWsName Then
            IsSheetNameUsed = True
            Exit Function
        End If
    Next buf
    IsSheetNameUsed = False
End Function

' --------------------------------------------------------------
' ブックが保護されていないか
' ※ ブックの保護時、シートの追加・削除・移動・名前変更 ができない
'   戻り値:True/ブックが保護されていない
'--------------------------------------------------------------
Function IsUnProtectBook(ByRef wb As Workbook) As Boolean
    IsUnProtectBook = Not wb.ProtectStructure
End Function

' --------------------------------------------------------------
' 表示されているシートが1枚の時、そのシートが移動対象か
'  ※表示シートが1枚のとき、表示されているシートを移動できない
'  srcWbObj:確認対象のブックオブジェクト
'  srcWs   :移動したいシート名
'  戻り値:True/移動可能(表示シートが2枚以上 or 移動対象が非表示)
'--------------------------------------------------------------
Function IsAllowedToMoveSheet(ByRef srcWbObj As Workbook, _
                ByRef srcWsName As String) As Boolean
    Dim i As Long
    Dim visibleCount As Long
    
    ' シートの存在確認は呼び出し元で行うこと!
    
    ' 非表示のシートなら、移動可能
    If srcWbObj.Worksheets(srcWsName).Visible <> xlSheetVisible Then
        IsAllowedToMoveSheet = True
        Exit Function
    End If
    
    '表示中のシートをカウントする
    For i = 1 To srcWbObj.Worksheets.Count
        If srcWbObj.Worksheets(i).Visible = xlSheetVisible Then
            visibleCount = visibleCount + 1
            If visibleCount >= 2 Then Exit For
        End If
    Next i
    ' 表示中のシートが2枚以上なら、シートを移動可能
    IsAllowedToMoveSheet = (visibleCount >= 2)
End Function
【実行サンプル】

● 実行前
プログラム実行前の画像

● 実行後
プログラム実行後の画像

ページの先頭へ