- 技術 💻
VBAのシート操作とブック操作まとめ 追加・コピー・削除・保存
VBAのシート操作は「どのブックの・どのシートを」を先に変数へ入れ、その変数に Add・Copy・Move・Delete・Name・Visible を1行ずつ書くのが基本です。 ブックも同じで、Workbooks.Open が返す Workbook を変数で受け、SaveAs と Close に引数を明示すれば、画面の状態に左右されない処理になります。
この記事では、やりたい操作から1行のコードを引ける逆引き表、各メソッドの引数一覧、シートの存在確認・全シートのループ・シート名のチェック・確認メッセージの抑止といった定型を、コピーして使えるコードで整理します。
確認環境:Windows 版 Excel の VBA を前提に、各メソッド・プロパティの構文と引数を Microsoft Learn の VBA リファレンスおよび Microsoft サポートのページ(2026-10-05 閲覧)と照合して書いています。Excel の画面の出力例は載せていません。シート名をチェックする2つの関数(文字列の処理だけで書いたもの)は、LibreOffice 24.2.7.2 の Basic(VBA 互換モード)で動かし、その出力を載せています。
この記事の結論
- 対象は必ず変数で受けます。
Set wb = ThisWorkbook、Set ws = wb.Worksheets("集計")と書いてから操作すると、別のブックが手前にあっても同じ結果になります。 - Add・Copy・Move は Before か After を必ず指定します。 省略すると、Add はアクティブなシートの前に入り、Copy と Move は新しいブックを作ります。
- 名前を付ける前に、存在確認と名前のチェックを通します。 同じ名前のシートがある場合や、使えない文字を含む場合は、Excel が受け付けずに実行時エラーになります。
- Delete と上書きの SaveAs は確認メッセージが出ます。
Application.DisplayAlerts = Falseで抑止し、エラー時も通る場所で True に戻します。 - Close は SaveChanges を明示します。 保存して閉じるのか、保存せずに閉じるのかをコードに書いておくと、途中で問い合わせが出ません。
シート操作・ブック操作の逆引き表
wb は Workbook、ws は Worksheet の変数です(入れ方は次の章)。
| やりたい操作 | 1行のコード |
|---|---|
| 末尾にシートを追加する | Set ws = wb.Worksheets.Add(After:=wb.Sheets(wb.Sheets.Count)) |
| 先頭にシートを追加する | Set ws = wb.Worksheets.Add(Before:=wb.Sheets(1)) |
| シートを3枚まとめて追加する | wb.Worksheets.Add After:=wb.Sheets(wb.Sheets.Count), Count:=3 |
| 同じブックの末尾にコピーする | ws.Copy After:=wb.Sheets(wb.Sheets.Count) |
| 新しいブックにコピーする | ws.Copy |
| 複数のシートを新しいブックにコピーする | wb.Worksheets(Array("4月", "5月")).Copy |
| シートを先頭へ移動する | ws.Move Before:=wb.Sheets(1) |
| シートを別のブックへ移動する | ws.Move After:=wbDst.Sheets(wbDst.Sheets.Count) |
| シートの名前を変える | ws.Name = "集計_10月" |
| シートを削除する | ws.Delete |
| シートを非表示にする | ws.Visible = xlSheetHidden |
| 画面の操作では再表示できない形で隠す | ws.Visible = xlSheetVeryHidden |
| シートを再表示する | ws.Visible = xlSheetVisible |
| シートの枚数を調べる | n = wb.Worksheets.Count |
| 新しいブックを作る | Set wb = Workbooks.Add |
| ブックを開く | Set wb = Workbooks.Open(Filename:="C:\work\data.xlsx") |
| 読み取り専用で開く | Set wb = Workbooks.Open(Filename:="C:\work\data.xlsx", ReadOnly:=True) |
| 上書き保存する | wb.Save |
| 名前を付けて保存する(xlsx) | wb.SaveAs Filename:="C:\work\out.xlsx", FileFormat:=xlOpenXMLWorkbook |
| マクロ有効ブックで保存する(xlsm) | wb.SaveAs Filename:="C:\work\out.xlsm", FileFormat:=xlOpenXMLWorkbookMacroEnabled |
| 保存して閉じる | wb.Close SaveChanges:=True |
| 保存せずに閉じる | wb.Close SaveChanges:=False |
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「VBAのシート操作とブック操作まとめ 追加・コピー・削除・保存」
どのブックのどのシートを指すかを決める
シート操作でつまずく原因の多くは、コードが指している対象が思っていたものと違うことです。先に「どのブックか」「どの種類のシートか」を決めます。
ThisWorkbook と ActiveWorkbook の違い
| 書き方 | 指すブック | 向いている場面 |
|---|---|---|
ThisWorkbook |
実行中のマクロのコードが入っているブック | マクロと同じブックのシートを操作するとき |
ActiveWorkbook |
いちばん手前のウィンドウに表示されているブック | 利用者が開いている任意のブックを対象にするとき |
Workbooks("data.xlsx") |
開いているブックのうち、その名前のもの | 名前が決まっている別のブックを指すとき |
Workbooks.Open(...) の戻り値 |
いま開いたブック | 開いた直後から変数で扱うとき |
Microsoft Learn には、ThisWorkbook は「マクロのコードが実行されているブック」を返し、アドインの中からアドイン自身のブックを指す方法はこれだけだと書かれています。ActiveWorkbook は手前のウィンドウのブックを返し、ウィンドウが1つも開いていないときは Nothing を返します。
Worksheets・Sheets・ActiveSheet・コード名の違い
| 書き方 | 指すもの | 含まれるシートの種類 |
|---|---|---|
wb.Worksheets("集計") |
名前で指定したワークシート | ワークシートだけ |
wb.Sheets("集計") |
名前で指定したシート | ワークシートとグラフシートの両方 |
wb.Worksheets(1) |
ワークシートだけを数えた1番目 | ワークシートだけ |
wb.Sheets(1) |
すべての種類を通して数えた1番目(左端) | ワークシートとグラフシートの両方 |
ActiveSheet |
アクティブなブックで手前に表示されているシート | 種類を問わない |
Sheet1(コード名) |
プロパティ ウィンドウの (Name) に表示される名前のシート | コードが入っているブックのシート |
コード名は、シートの見出しに表示される名前とは別のものです。Microsoft Learn によると、シートを作った時点では両者は同じですが、見出しの名前を変えてもコード名は変わらず、コード名は実行中のコードからは変更できません。利用者がシート名を書き換えてもコードが動き続けるのは、この性質によるものです。
選び方の判断表
| 条件 | 選ぶもの |
|---|---|
| マクロと同じブックのシートを操作する | ThisWorkbook |
| 利用者が開いているブックを対象にする | 最初に Set wb = ActiveWorkbook で受け、以降は wb を使う |
| セルの読み書きをする | Worksheets(グラフシートを対象にしない) |
| 位置(末尾・先頭)を指定する、すべての種類を数える | Sheets |
| シート名が利用者に変更される可能性がある | コード名(Sheet1 など) |
| 別のブックのシートを指す | wb.Worksheets("名前")(コード名は別のブックには使えない) |
位置の指定に Sheets を使うのは、グラフシートが混ざったブックでも「全体の末尾」を正しく指せるからです。
Option Explicit
Sub Sample_SetTargets()
Dim wb As Workbook
Dim ws As Worksheet
Set wb = ThisWorkbook ' マクロが入っているブック
Set ws = wb.Worksheets("集計") ' その中の「集計」シート
ws.Range("A1").Value = "更新日"
ws.Range("B1").Value = Date
End Sub
引数の一覧(Microsoft公式リファレンスの記載)
シートの追加:Add(Before, After, Count, Type)
| 引数 | 省略 | 内容 |
|---|---|---|
| Before | 可 | このシートの前に追加する |
| After | 可 | このシートの後ろに追加する |
| Count | 可 | 追加する枚数。既定値は選択しているシートの数 |
| Type | 可 | シートの種類。xlWorksheet・xlChart・xlExcel4MacroSheet・xlExcel4IntlMacroSheet のいずれか。テンプレートのパスも指定できる。既定値は xlWorksheet |
- 戻り値は、追加されたシートを表すオブジェクトです。
Set ws = ...Add(...)で受け取れます。 - Before と After を両方省略すると、アクティブなシートの前に追加されます。
- 32 ビット版の Excel 2010 では、一度に 255 枚を超えるシートは作成できないという注記があります。
コピーと移動:Copy(Before, After)/Move(Before, After)
| 引数 | 省略 | 内容 |
|---|---|---|
| Before | 可 | このシートの前に置く。After と同時には指定できない |
| After | 可 | このシートの後ろに置く。Before と同時には指定できない |
- Before と After を両方省略すると、新しいブックが作られ、そこへコピー(または移動)されます。
- Copy で新しく作られたブックは ActiveWorkbook になり、シートは1枚だけで、元のシートの名前とコード名を引き継ぎます。
- コピー元とコピー先は、同じ Excel(同じ Application のインスタンス)の中にある必要があります。別のインスタンスのブックを指定すると実行時エラー 1004 になると記載されています。
削除と表示:Delete/Visible
| メンバー | 内容 |
|---|---|
ws.Delete |
引数なし。既定では確認のダイアログが出る。戻り値は Boolean で、利用者がキャンセルを選ぶと False、削除を選ぶと True |
ws.Visible |
XlSheetVisibility の値を取得・設定する |
| Visible の値 | 数値 | 内容 |
|---|---|---|
| xlSheetVisible | -1 | シートを表示する |
| xlSheetHidden | 0 | 非表示にする。利用者がメニューから再表示できる |
| xlSheetVeryHidden | 2 | 非表示にする。利用者の画面の操作では再表示できず、プロパティを設定して戻す |
ブックを開く:Workbooks.Open の主な引数
Open は 15 個の引数を持ちます。順番は FileName, UpdateLinks, ReadOnly, Format, Password, WriteResPassword, IgnoreReadOnlyRecommended, Origin, Delimiter, Editable, Notify, Converter, AddToMru, Local, CorruptLoad です。よく使うものを抜き出します。
| 引数 | 内容 |
|---|---|
| FileName | 開くブックのファイル名 |
| UpdateLinks | 外部参照(リンク)の更新方法。0 は更新しない、3 は開くときに更新する。省略すると利用者に問い合わせる |
| ReadOnly | True で読み取り専用として開く |
| Password | 保護されたブックを開くためのパスワード。省略すると利用者に問い合わせる |
| WriteResPassword | 書き込みパスワード。省略すると利用者に問い合わせる |
| IgnoreReadOnlyRecommended | True で「読み取り専用を推奨」のメッセージを出さない |
| AddToMru | True で最近使ったファイルの一覧に加える。既定値は False |
| CorruptLoad | xlNormalLoad(既定)・xlRepairFile・xlExtractData |
戻り値は、開いたブックを表す Workbook です。コードから開いたファイルのマクロは既定で有効になり、その扱いは AutomationSecurity プロパティで設定すると書かれています。
名前を付けて保存:SaveAs の主な引数
SaveAs は 12 個の引数を持ちます。順番は FileName, FileFormat, Password, WriteResPassword, ReadOnlyRecommended, CreateBackup, AccessMode, ConflictResolution, AddToMru, TextCodepage, TextVisualLayout, Local です。
| 引数 | 内容 |
|---|---|
| FileName | 保存するファイル名。フルパスを書ける。パスを書かないと現在のフォルダーに保存される |
| FileFormat | 保存する形式(XlFileFormat)。既存のファイルは最後に指定した形式、新しいファイルは使っている Excel の版の形式が既定 |
| Password | 読み取りパスワード。大文字と小文字を区別し、15 文字まで |
| WriteResPassword | 書き込みパスワード |
| ReadOnlyRecommended | True で、開くときに読み取り専用を勧めるメッセージを出す |
| CreateBackup | True でバックアップ ファイルを作る |
| AddToMru | True で最近使ったファイルの一覧に加える。既定値は False |
FileFormat に指定する定数のうち、よく使うものです。
| 定数 | 数値 | 形式 | 拡張子 |
|---|---|---|---|
| xlOpenXMLWorkbook | 51 | Excel ブック | xlsx |
| xlOpenXMLWorkbookMacroEnabled | 52 | マクロ有効ブック | xlsm |
| xlExcel12 | 50 | バイナリ ブック | xlsb |
| xlExcel8 | 56 | Excel 97-2003 ブック | xls |
| xlOpenXMLTemplate | 54 | テンプレート | xltx |
| xlOpenXMLTemplateMacroEnabled | 53 | マクロ有効テンプレート | xltm |
| xlCSV | 6 | CSV | csv |
| xlCSVUTF8 | 62 | UTF-8 の CSV | csv |
| xlUnicodeText | 42 | Unicode テキスト | txt |
| xlWorkbookDefault | 51 | ブックの既定の形式 | xlsx |
閉じる:Close(SaveChanges, FileName, RouteWorkbook)
| 引数 | 内容 |
|---|---|
| SaveChanges | ブックに変更があるときに、保存するかどうかを指定する。True で保存する。変更が無いときは無視される |
| FileName | この名前で変更を保存する。まだファイル名が無いブックを SaveChanges:=True で閉じるときに使われ、省略すると利用者に名前を問い合わせる |
| RouteWorkbook | 回覧の設定があるブックを次の宛先へ送るかどうか |
Close ではブック内の Auto_Close マクロは実行されないと書かれています。
シートを追加・コピー・移動・改名・削除するコード
ここからのコードは、標準モジュールにそのまま貼れる形です。同じモジュールに、後の章の SheetExists と SheetNameProblem も貼ってください。
末尾に追加して名前を付ける
Option Explicit
Sub Sample_AddSheet()
Dim wb As Workbook
Dim ws As Worksheet
Const NEW_NAME As String = "集計_10月"
Set wb = ThisWorkbook
If SheetExists(wb, NEW_NAME) Then
MsgBox "「" & NEW_NAME & "」は既にあります。", vbInformation
Exit Sub
End If
Set ws = wb.Worksheets.Add(After:=wb.Sheets(wb.Sheets.Count))
ws.Name = NEW_NAME
End Sub
追加と名前の設定は2行に分けます。Add の戻り値を ws で受けておけば、追加後にどのシートがアクティブになっているかを気にせずに名前を付けられます。
コピーして名前を付ける
Copy は戻り値でコピー先のシートを受け取る形ではないので、置いた位置からコピー先を取り出します。末尾にコピーしたなら、コピー後の末尾のシートがコピー先です。
Sub Sample_CopySheet()
Dim wb As Workbook
Dim wsSrc As Worksheet
Dim wsNew As Worksheet
Dim newName As String
Set wb = ThisWorkbook
Set wsSrc = wb.Worksheets("ひな形")
newName = "備品台帳_" & Format(Date, "yyyymmdd")
If SheetNameProblem(newName) <> "" Then
MsgBox SheetNameProblem(newName), vbExclamation
Exit Sub
End If
If SheetExists(wb, newName) Then
MsgBox "「" & newName & "」は既にあります。", vbInformation
Exit Sub
End If
wsSrc.Copy After:=wb.Sheets(wb.Sheets.Count)
Set wsNew = wb.Sheets(wb.Sheets.Count) ' 末尾に置いたので、末尾がコピー先
wsNew.Name = newName
End Sub
新しいブックにコピーして保存する
Before と After を省略した Copy は新しいブックを作り、そのブックが ActiveWorkbook になります。直後に変数で受ければ、以降は画面の状態に関係なく扱えます。
Sub Sample_CopyToNewBook()
Dim wbNew As Workbook
ThisWorkbook.Worksheets("集計").Copy
Set wbNew = ActiveWorkbook ' Copy の直後に受ける
wbNew.SaveAs Filename:=ThisWorkbook.Path & "\集計_配布用.xlsx", _
FileFormat:=xlOpenXMLWorkbook
wbNew.Close SaveChanges:=False
End Sub
移動する・並べ替える
Sub Sample_MoveSheet()
Dim wb As Workbook
Set wb = ThisWorkbook
wb.Worksheets("目次").Move Before:=wb.Sheets(1) ' 先頭へ
wb.Worksheets("集計").Move After:=wb.Sheets(wb.Sheets.Count) ' 末尾へ
End Sub
表示を切り替える
Sub Sample_HideAndShow()
Dim wb As Workbook
Dim sh As Object
Set wb = ThisWorkbook
wb.Worksheets("設定").Visible = xlSheetVeryHidden ' 画面の操作では再表示できない
' すべてのシートを表示に戻す
For Each sh In wb.Sheets
sh.Visible = xlSheetVisible
Next sh
End Sub
確認メッセージを出さずに削除する(DisplayAlertsを戻す書き方)
Delete は既定で確認のダイアログを出します。Application.DisplayAlerts = False で抑止できますが、False のまま処理が続くと、以降の確認メッセージもすべて既定の応答で進みます。途中でエラーになっても必ず True に戻るよう、戻す行を出口の1か所に置きます。
Sub Sample_DeleteSheet()
Dim wb As Workbook
Const TARGET As String = "作業用"
On Error GoTo ErrHandler
Set wb = ThisWorkbook
If Not SheetExists(wb, TARGET) Then Exit Sub
Application.DisplayAlerts = False
wb.Worksheets(TARGET).Delete
CleanUp:
Application.DisplayAlerts = True ' 正常時もエラー時もここを通る
Exit Sub
ErrHandler:
MsgBox "エラー " & Err.Number & ":" & Err.Description, vbExclamation
Resume CleanUp
End Sub
Exit Sub を CleanUp: より前に書く場合は、DisplayAlerts を False にする前に置きます。上のコードでは、存在確認の Exit Sub が False にする行より前にあります。
シートの存在確認と全シートのループ
シートがあるかを調べる関数
エラーの発生を判定に使わず、名前を順に比べる書き方です。エラー処理の設定に影響されないので、どのプロシージャからでも呼べます。
' wb に sheetName という名前のシートがあれば True を返す
Function SheetExists(ByVal wb As Workbook, ByVal sheetName As String) As Boolean
Dim sh As Object ' グラフシートも含めて調べるので Object で受ける
For Each sh In wb.Sheets
If StrComp(sh.Name, sheetName, vbTextCompare) = 0 Then
SheetExists = True
Exit Function
End If
Next sh
SheetExists = False
End Function
wb.Sheetsを回しているのは、グラフシートの名前も含めて重なりを調べるためです。vbTextCompareで比べ、大文字と小文字だけが違う名前も同じ名前として見つけます。
全シートを For Each で処理する
Sub Sample_LoopAllSheets()
Dim wb As Workbook
Dim ws As Worksheet
Dim sh As Object
Set wb = ThisWorkbook
' ワークシートだけを処理する(セルを読み書きする処理はこちら)
For Each ws In wb.Worksheets
Debug.Print ws.Index, ws.Name, ws.CodeName, ws.Visible
Next ws
' グラフシートも含めてすべて処理する
For Each sh In wb.Sheets
Debug.Print sh.Index, sh.Name, TypeName(sh)
Next sh
End Sub
| 回す対象 | ループ変数の型 | 向いている処理 |
|---|---|---|
wb.Worksheets |
Worksheet |
セルの読み書き、書式の設定 |
wb.Sheets |
Object |
名前の一覧、表示の切り替え、位置の確認 |
ループの中で削除するときは後ろから
For Each で回している最中にシートを削除すると、回している対象そのものが変わります。削除を伴う処理は、番号を使って後ろから前へ進めると、残りの番号がずれません。
Sub Sample_DeleteByPrefix()
Dim wb As Workbook
Dim i As Long
On Error GoTo ErrHandler
Set wb = ThisWorkbook
Application.DisplayAlerts = False
For i = wb.Worksheets.Count To 1 Step -1
If Left(wb.Worksheets(i).Name, 4) = "tmp_" Then
wb.Worksheets(i).Delete
End If
Next i
CleanUp:
Application.DisplayAlerts = True
Exit Sub
ErrHandler:
MsgBox "エラー " & Err.Number & ":" & Err.Description, vbExclamation
Resume CleanUp
End Sub
シート名の禁止文字と31文字制限をチェックする
Microsoft サポートのページには、シート名の決まりとして次の5つが挙げられています。
| 決まり | 内容 |
|---|---|
| 空にできない | 名前を空白のままにはできない |
| 長さ | 31 文字まで |
| 使えない文字 | / \ ? * : [ ] の7種類 |
| アポストロフィ | 先頭と末尾には置けない(途中には置ける) |
| 予約された名前 | History(日本語版のページでは「履歴」)は Excel が内部で使うため付けられない |
この5つを順に調べ、使えない理由を文字列で返す関数と、使える形に直した名前を返す関数です。
' シート名として使えない理由を返す(使える名前なら空文字を返す)
Function SheetNameProblem(ByVal newName As String) As String
Const NG_CHARS As String = "/\?*:[]"
Dim i As Long
If Len(newName) = 0 Then
SheetNameProblem = "名前が空です"
Exit Function
End If
If Len(newName) > 31 Then
SheetNameProblem = "31文字を超えています(" & Len(newName) & "文字)"
Exit Function
End If
For i = 1 To Len(NG_CHARS)
If InStr(newName, Mid(NG_CHARS, i, 1)) > 0 Then
SheetNameProblem = "使えない文字 " & Mid(NG_CHARS, i, 1) & " を含んでいます"
Exit Function
End If
Next i
If Left(newName, 1) = "'" Or Right(newName, 1) = "'" Then
SheetNameProblem = "先頭または末尾がアポストロフィです"
Exit Function
End If
If StrComp(newName, "History", vbTextCompare) = 0 Or newName = "履歴" Then
SheetNameProblem = "予約されている名前です"
Exit Function
End If
SheetNameProblem = ""
End Function
' 使えない文字を置き換え、31文字に切り詰めた名前を返す
Function SafeSheetName(ByVal rawName As String) As String
Const NG_CHARS As String = "/\?*:[]"
Dim i As Long
Dim s As String
s = rawName
For i = 1 To Len(NG_CHARS)
s = Replace(s, Mid(NG_CHARS, i, 1), "_")
Next i
Do While Left(s, 1) = "'"
s = Mid(s, 2)
Loop
Do While Right(s, 1) = "'"
s = Left(s, Len(s) - 1)
Loop
If Len(s) > 31 Then s = Left(s, 31)
If Len(s) = 0 Then s = "Sheet"
If StrComp(s, "History", vbTextCompare) = 0 Or s = "履歴" Then s = s & "_"
SafeSheetName = s
End Function
この2つの関数に10個の名前を渡した結果です(LibreOffice 24.2.7.2 の Basic を VBA 互換モードにして実行。左から、渡した名前、SheetNameProblem の戻り値、SafeSheetName の戻り値)。
[2026年10月] -> [] safe=[2026年10月]
[] -> [名前が空です] safe=[Sheet]
[2026/10] -> [使えない文字 / を含んでいます] safe=[2026_10]
[備品[貸出]] -> [使えない文字 [ を含んでいます] safe=[備品_貸出_]
[A:B] -> [使えない文字 : を含んでいます] safe=[A_B]
['集計'] -> [先頭または末尾がアポストロフィです] safe=[集計]
[history] -> [予約されている名前です] safe=[history_]
[履歴] -> [予約されている名前です] safe=[履歴_]
[あああああああああああああああああああああああああああああああ] -> [] safe=[あああああああああああああああああああああああああああああああ]
[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] -> [31文字を超えています(32文字)] safe=[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
日付を名前に入れるときは、Format(Date, "yyyy/mm/dd") のようにスラッシュが入る書式を避け、"yyyymmdd" や "yyyy-mm-dd" を使います。全角の「あ」31 文字が通り、半角 32 文字が止まることから、数えているのはバイト数ではなく文字数だと分かります。
重ならない名前を作る関数
同じ名前が既にあるときに、末尾へ (2)、(3) と番号を付けた名前を返します。番号を足しても 31 文字に収まるよう、元の名前のほうを切り詰めます。
' wb の中でまだ使われていない名前を返す(baseName、baseName(2)、baseName(3) …)
Function UniqueSheetName(ByVal wb As Workbook, ByVal baseName As String) As String
Dim candidate As String
Dim suffix As String
Dim n As Long
candidate = SafeSheetName(baseName)
n = 1
Do While SheetExists(wb, candidate)
n = n + 1
suffix = "(" & n & ")"
candidate = Left(SafeSheetName(baseName), 31 - Len(suffix)) & suffix
Loop
UniqueSheetName = candidate
End Function
使うときは ws.Name = UniqueSheetName(wb, "集計") と書きます。
名前の設定とコピーで実行時エラー1004になる条件
実行時エラー 1004 は、VBA の文法ではなく、Excel 側が操作を受け付けなかったときに伝わってくるエラーです。シートとブックの操作では、次の条件で起こります。
| 条件 | 起こる行の例 | 先に行う確認 |
|---|---|---|
| 同じブックに同じ名前のシートが既にある | ws.Name = "集計" |
SheetExists(wb, "集計") |
| 名前が空、または 31 文字を超えている | ws.Name = "" |
SheetNameProblem(名前) |
| 名前に使えない文字が入っている | ws.Name = "2026/10" |
SheetNameProblem(名前) |
| 名前の先頭か末尾がアポストロフィ、または予約された名前 | ws.Name = "History" |
SheetNameProblem(名前) |
| 別の Excel(別のインスタンス)で開いているブックへコピーする | ws.Copy After:=別インスタンスのシート |
コピー先を同じ Excel の中で開く |
最後の行は Microsoft Learn の Copy メソッドのページに、実行時エラー 1004 になる例として書かれています。
1004 はメッセージの文面が場面によって変わるので、エラー処理では番号だけでなく Err.Description も一緒に表示すると、どの条件に当たったかが分かります。
Sub Sample_RenameWithCheck()
Dim wb As Workbook
Dim ws As Worksheet
Dim newName As String
Dim problem As String
On Error GoTo ErrHandler
Set wb = ThisWorkbook
Set ws = wb.Worksheets("Sheet1")
newName = "集計_10月"
problem = SheetNameProblem(newName)
If problem <> "" Then
MsgBox "この名前は付けられません:" & problem, vbExclamation
Exit Sub
End If
If SheetExists(wb, newName) Then
MsgBox "「" & newName & "」は既にあります。", vbInformation
Exit Sub
End If
ws.Name = newName
Exit Sub
ErrHandler:
MsgBox "エラー " & Err.Number & ":" & Err.Description, vbExclamation
End Sub
ブックを開く・保存する・閉じるコード
開く(既に開いていればそのブックを使う)
' フルパスで指定したブックを返す。既に開いていればそのブックを、無ければ開いて返す
Function OpenOrGetWorkbook(ByVal fullPath As String, _
Optional ByVal asReadOnly As Boolean = False) As Workbook
Dim wb As Workbook
For Each wb In Workbooks
If StrComp(wb.FullName, fullPath, vbTextCompare) = 0 Then
Set OpenOrGetWorkbook = wb
Exit Function
End If
Next wb
Set OpenOrGetWorkbook = Workbooks.Open(Filename:=fullPath, _
UpdateLinks:=0, _
ReadOnly:=asReadOnly)
End Function
UpdateLinks:=0 を付けているのは、省略すると外部参照の更新について利用者に問い合わせが出るためです。値を読むだけなら ReadOnly:=True で開くと、元のファイルを書き換える心配がありません。
別のブックからシートを取り込み、保存して閉じる
開く・コピーする・保存する・閉じるを1つにまとめた例です。
Sub Sample_ImportSheetAndSave()
Dim wbDst As Workbook
Dim wbSrc As Workbook
Dim srcPath As String
Dim newName As String
On Error GoTo ErrHandler
Set wbDst = ThisWorkbook
srcPath = wbDst.Path & "\備品台帳.xlsx"
Set wbSrc = Workbooks.Open(Filename:=srcPath, UpdateLinks:=0, ReadOnly:=True)
' 取り込み先で重ならない名前を先に決める
newName = UniqueSheetName(wbDst, "台帳_" & Format(Date, "yyyymmdd"))
wbSrc.Worksheets("台帳").Copy After:=wbDst.Sheets(wbDst.Sheets.Count)
wbDst.Sheets(wbDst.Sheets.Count).Name = newName
wbSrc.Close SaveChanges:=False ' 元のブックは保存せずに閉じる
Set wbSrc = Nothing
wbDst.Save ' 取り込み先は上書き保存
Exit Sub
ErrHandler:
MsgBox "エラー " & Err.Number & ":" & Err.Description, vbExclamation
If Not wbSrc Is Nothing Then wbSrc.Close SaveChanges:=False
End Sub
名前を付けて保存する
Sub Sample_SaveAsNewFile()
Dim wb As Workbook
Dim outPath As String
On Error GoTo ErrHandler
Set wb = Workbooks.Add
wb.Worksheets(1).Range("A1").Value = "備品名"
outPath = ThisWorkbook.Path & "\備品一覧_" & Format(Date, "yyyymmdd") & ".xlsx"
Application.DisplayAlerts = False ' 同じ名前のファイルがあれば上書きする
wb.SaveAs Filename:=outPath, FileFormat:=xlOpenXMLWorkbook
Application.DisplayAlerts = True
wb.Close SaveChanges:=False
Exit Sub
ErrHandler:
Application.DisplayAlerts = True
MsgBox "エラー " & Err.Number & ":" & Err.Description, vbExclamation
End Sub
- 拡張子と FileFormat はそろえて書きます。 xlsx なら xlOpenXMLWorkbook、xlsm なら xlOpenXMLWorkbookMacroEnabled です。
- 初めて保存するブックには Save ではなく SaveAs を使い、ファイル名を指定します(Save メソッドのページの記載)。
- 同じ名前のファイルがあるとき、上書きの確認の既定の応答は「いいえ」ですが、DisplayAlerts が False のときは Excel が「はい」を選び、既存のファイルが上書きされます。上書きしたくない場合は、DisplayAlerts を True のままにするか、ファイル名に日時を入れます。
Save・SaveAs・Close の使い分け
| やりたいこと | 書き方 |
|---|---|
| いまのファイル名のまま保存する | wb.Save |
| 初めて保存する、別の名前や形式で保存する | wb.SaveAs Filename:=..., FileFormat:=... |
| 保存して閉じる | wb.Close SaveChanges:=True |
| 変更を捨てて閉じる | wb.Close SaveChanges:=False |
| 保存せずに「保存済み」の扱いにする | wb.Saved = True |
確かめて分かったこと
Microsoft Learn とサポートのページを開いて照合し、関数を動かして分かった点です。
- Add・Copy・Move は、位置を省略したときの動きがそれぞれ違います。 Add はアクティブなシートの前に入り、Copy と Move は新しいブックを作ります。
- Add の Count の既定値は 1 ではなく「選択しているシートの数」です。 複数のシートを選んだ状態で実行すると、その枚数だけ追加されます。1 枚だけ追加したいときは
Count:=1を書くと確実です。 - DisplayAlerts は、コードの実行が終わると Excel が True に戻します(別のプロセスから実行している場合を除く)。それでも、同じマクロの後半で確認メッセージが必要な処理があるなら、直後に自分で True に戻す必要があります。
- DisplayAlerts が False のとき、SaveAs の上書き確認は「はい」が選ばれます。 既定の応答(いいえ)とは逆になる点に気を付けます。
- Delete は Boolean を返します。 確認のダイアログを出したままにする場合は、
If ws.Delete Thenの形で、利用者が削除を選んだかどうかを受け取れます。 - シート名の長さは文字数で数えます。 全角 31 文字はチェックを通り、半角 32 文字は止まりました(上の出力)。
よくある質問
Q. Worksheets と Sheets の違いは何ですか? A. Worksheets はワークシートだけ、Sheets はグラフシートも含むすべてのシートの集まりです。セルを読み書きする処理は Worksheets、位置の指定や名前の重なりの確認は Sheets を使います。
Q. ThisWorkbook と ActiveWorkbook の違いは何ですか? A. ThisWorkbook はマクロのコードが入っているブック、ActiveWorkbook は手前に表示されているブックです。マクロと同じブックを操作するなら ThisWorkbook を使うと、別のブックが手前にあっても対象が変わりません。
Q. シートをコピーしたあと、コピー先のシートを変数に入れるにはどうしますか?
A. コピーした位置から取り出します。ws.Copy After:=wb.Sheets(wb.Sheets.Count) の直後に Set wsNew = wb.Sheets(wb.Sheets.Count) と書けば、末尾に置かれたコピー先を受け取れます。
Q. シートを削除するときの確認メッセージを出さないようにできますか?
A. Application.DisplayAlerts = False を Delete の前に書くと出なくなります。削除の直後と、エラー処理の出口の両方で True に戻してください。
Q. シート名を変更できないときは何を確かめますか?
A. 同じ名前のシートが既に無いか、31 文字を超えていないか、/ \ ? * : [ ] を含んでいないか、の3点です。この記事の SheetExists と SheetNameProblem を通すと、どれに当たったかが分かります。
まとめ
- 対象のブックとシートは変数で受けてから操作する(
Set wb = ThisWorkbook、Set ws = wb.Worksheets("名前")) - Add・Copy・Move は Before か After を明示する。省略時は Add がアクティブなシートの前、Copy と Move が新しいブック
- セルの処理は Worksheets、位置と名前の確認は Sheets を使う
- 名前を付ける前に SheetExists と SheetNameProblem を通すと、実行時エラー 1004 になる条件を先に見つけられる
- シート名は 31 文字まで、使えない文字は7種類。先頭と末尾のアポストロフィ、History も付けられない
- DisplayAlerts は False にした直後の処理だけを挟み、出口の1か所で True に戻す
- Open は戻り値を変数で受け、SaveAs は FileFormat、Close は SaveChanges を明示する
参考・出典
いずれも 2026-10-05 に閲覧しました。
- Microsoft Learn「Sheets.Add method (Excel)」 https://learn.microsoft.com/en-us/office/vba/api/excel.sheets.add
- Microsoft Learn「Worksheet.Copy method (Excel)」 https://learn.microsoft.com/en-us/office/vba/api/excel.worksheet.copy
- Microsoft Learn「Worksheet.Move method (Excel)」 https://learn.microsoft.com/en-us/office/vba/api/excel.worksheet.move
- Microsoft Learn「Worksheet.Delete method (Excel)」 https://learn.microsoft.com/en-us/office/vba/api/excel.worksheet.delete
- Microsoft Learn「Worksheet.Name property (Excel)」 https://learn.microsoft.com/en-us/office/vba/api/excel.worksheet.name
- Microsoft Learn「Worksheet.Visible property (Excel)」 https://learn.microsoft.com/en-us/office/vba/api/excel.worksheet.visible
- Microsoft Learn「XlSheetVisibility enumeration (Excel)」 https://learn.microsoft.com/en-us/office/vba/api/excel.xlsheetvisibility
- Microsoft Learn「Worksheet.CodeName property (Excel)」 https://learn.microsoft.com/en-us/office/vba/api/excel.worksheet.codename
- Microsoft Learn「Sheets object (Excel)」 https://learn.microsoft.com/en-us/office/vba/api/excel.sheets
- Microsoft Learn「Worksheets object (Excel)」 https://learn.microsoft.com/en-us/office/vba/api/excel.worksheets
- Microsoft Learn「Application.ActiveSheet property (Excel)」 https://learn.microsoft.com/en-us/office/vba/api/excel.application.activesheet
- Microsoft Learn「Application.ThisWorkbook property (Excel)」 https://learn.microsoft.com/en-us/office/vba/api/excel.application.thisworkbook
- Microsoft Learn「Application.ActiveWorkbook property (Excel)」 https://learn.microsoft.com/en-us/office/vba/api/excel.application.activeworkbook
- Microsoft Learn「Workbooks object (Excel)」 https://learn.microsoft.com/en-us/office/vba/api/excel.workbooks
- Microsoft Learn「Workbooks.Add method (Excel)」 https://learn.microsoft.com/en-us/office/vba/api/excel.workbooks.add
- Microsoft Learn「Workbooks.Open method (Excel)」 https://learn.microsoft.com/en-us/office/vba/api/excel.workbooks.open
- Microsoft Learn「Workbook.Save method (Excel)」 https://learn.microsoft.com/en-us/office/vba/api/excel.workbook.save
- Microsoft Learn「Workbook.SaveAs method (Excel)」 https://learn.microsoft.com/en-us/office/vba/api/excel.workbook.saveas
- Microsoft Learn「Workbook.Close method (Excel)」 https://learn.microsoft.com/en-us/office/vba/api/excel.workbook.close
- Microsoft Learn「XlFileFormat enumeration (Excel)」 https://learn.microsoft.com/en-us/office/vba/api/excel.xlfileformat
- Microsoft Learn「Application.DisplayAlerts property (Excel)」 https://learn.microsoft.com/en-us/office/vba/api/excel.application.displayalerts
- Microsoft Learn「Application-defined or object-defined error」 https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/application-defined-or-object-defined-error
- Microsoft サポート「ワークシートの名前を変更する」 https://support.microsoft.com/ja-jp/office/3f1f7148-ee83-404d-8ef0-9ff99fbad1f9
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「VBAのシート操作とブック操作まとめ 追加・コピー・削除・保存」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。