TL;DR —
FileCopy source, destinationはファイルを 1 行でコピーし、参照設定もいらず、コピー先に すでにあるものを無言で上書きします。誰もがつまずく落とし穴は、開いているファイルはコピー できないこと — マクロを実行しているそのブック自身も含めてです。どちらのパスもファイル名まで 含めた完全な形でなければならず、コピー先のフォルダーはあらかじめ存在していなければなりません。
Sub BackupReport()
' 両方の引数はフルパス — それぞれにファイル名まで含める
FileCopy "C:\Reports\March.xlsx", "C:\Backup\March.xlsx" ' Backup を無言で上書きする
End Sub
マクロが処理すべきファイルを見つけたあと、次にやることはたいていそれらに手を加えることです —
そしてその中でいちばん穏やかな操作が、ほかの何かが触れる前に、ひとつを安全な場所へコピーして
おくことです。初心者が最初の壁にぶつかるのもここです。FileCopy は閉じたファイルには完璧に
働くのに、開いているブックに向けたとたん error 70 で失敗します。その理由を理解すれば、
3 つのコピー道具のうち正しいものへいつでも手を伸ばせるようになります。
この記事で学べること
- 考え方の軸 — どのコピー道具が必要かは、ファイルが開いているかで決まる
FileCopyが警告なしで上書きする理由 —Nameステートメントとは正反対- 開いているブックに対して
FileCopyが error 70 で失敗する理由と、代わりに何を使うか - 両方の引数がフルパスでなければならず、コピー先フォルダーがあらかじめ存在していなければ ならない理由
- ワイルドカードと明示的な上書きフラグのために
FileSystemObject.CopyFileへ切り替える タイミング - たった今開いているブックを
SaveCopyAsでコピーする方法、そしてコピーしてからKillするとどうして移動になるのか
考え方の軸:3 つの状況に対応する 3 つのコピー道具
VBA に「ファイルをコピーする」単一のコマンドはありません — 3 つあり、互いに置き換えは効きません。 正しいものを選ぶ問いはいつも同じです。ファイルは開いているか、そしてワイルドカードは要るか?
FileCopy source, destination— 組み込みステートメント。参照設定なし、オブジェクトなし。 ひとつの閉じたファイルをコピーし、コピー先を無言で上書きします。ディスク上にある ファイルには、これが既定。FileSystemObject.CopyFile source, destination[, overwrite]— オブジェクトモデル版。仕事は 同じですが、ワイルドカード(*.xlsx)を受け付け、明示的な上書きフラグを取り、ツリー 全体を扱うCopyFolderの兄弟を持ちます。workbook.SaveCopyAs path— たった今開いているブックをコピーする唯一の正しい方法。 生きているファイルを乱さずに、スナップショットをディスクへ書き出します。
以下のすべては、この 3 つと、それぞれが属する状況から導かれる帰結です。まず「開いているか?」、 次に「パターンは要るか?」と問うて選びましょう。
FileCopy は無言で上書きする — Name とは正反対
FileCopy は決して尋ねません。コピー先にすでに何かがあれば、プロンプトもエラーもなしに
置き換えられます。これが問題になるのは、ディスク向けの兄弟ステートメントである
Name がちょうど逆のことをするからです — あちらは上書きを拒み、
エラーを発生させます。2 つの組み込みが、「コピー先が存在したら?」に対して 2 つの矛盾する
答えを返すのです。
FileCopy "C:\Reports\March.xlsx", "C:\Backup\March.xlsx" ' Backup\March.xlsx を警告なしで置き換える
無言の上書きが望みなら(バックアップを更新するなど)、それは便利です。そうでないなら — その
バックアップが昨日の唯一のコピーだったなら — FileCopy を呼ぶ前に、自分でコピー先をガード
しなければなりません。
If Dir("C:\Backup\March.xlsx") = "" Then ' 何もないときだけコピーする
FileCopy "C:\Reports\March.xlsx", "C:\Backup\March.xlsx"
End If
その 1 行の存在テストはファイルの存在を確認するの主題ですが、 ここではそれが、安全なバックアップと壊されたバックアップとの分かれ目になります。
error 70 の罠:FileCopy は開いているファイルをコピーできない
これはナンバーワンの FileCopy バグです。このステートメントは Windows に、コピー元への
排他的な読み取りアクセスと、コピー先への排他的な書き込みアクセスを要求します。開いている
ブックは Excel によってロックされているので、
FileCopy ThisWorkbook.FullName, "C:\Backup\live.xlsx" ' error 70 — "Permission denied"
は即座に失敗します — そしていちばんバックアップしたいファイル(あなたが作業中のそのファイル)
こそが、まさに開いているファイルなのです。コピー先が開いている、読み取り専用、あるいは
フォルダーへの権限がない場合にも、同じ error 70 が現れます。正しい抜け道は 2 つ。
- 自分のブックなら、
SaveCopyAsを使う — 閉じずに生きたファイルをコピーします(次節)。 - コードで開いた別のブックなら、まず
Closeしてから、ディスク上の ファイルをFileCopyする。
error 70 を On Error Resume Next で「直そう」としてはいけません — それはロックされたファイルを
無言の「コピーしない」に化けさせ、あなたのバックアップは結局一度も行われません。
両方の引数はフルパス — そしてフォルダーは存在していなければならない
2 つの構造的なルールが、繰り返し人をつまずかせます。
コピー先はフォルダーではなくフルパス。 FileCopy はコピー元からファイル名を推測しません。
FileCopy "C:\Reports\March.xlsx", "C:\Backup\" ' error 75 — パス/ファイルアクセスエラー
FileCopy "C:\Reports\March.xlsx", "C:\Backup\March.xlsx" ' 正しい — ファイル名を明示する
コピー先フォルダーはあらかじめ存在していなければならない。 FileCopy は C:\Backup\ を
あなたのために作ってはくれません。フォルダーがない可能性があるなら、まず MkDir で作りましょう —
ただし MkDir 自身はフォルダーがすでにあるとエラーになるので、こちらもガードします。
If Dir("C:\Backup", vbDirectory) = "" Then MkDir "C:\Backup"
FileCopy "C:\Reports\March.xlsx", "C:\Backup\March.xlsx"
FileSystemObject.CopyFile:ワイルドカードと明示的な上書きフラグ
たくさんのファイルを一度にコピーしたいとき、あるいは上書きを無言の既定ではなく決断に
したいときは、FileSystemObject に切り替えます。
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject") ' 遅延バインディング — どのマシンでも動く
fso.CopyFile "C:\Reports\*.xlsx", "C:\Backup\" ' ワイルドカード:.xlsx をすべて一度に
fso.CopyFile "C:\Reports\March.xlsx", "C:\Backup\March.xlsx", False ' Overwrite:=False → 存在すれば error 58
FileCopy にできなくて CopyFile にできることが 3 つあります。ワイルドカードパターンに
一致させること、上書きフラグを取って既存ファイルを無言で消す代わりに error 58 を発生
させること、そして — CopyFolder を使えば — ディレクトリツリー全体をコピーすること。ここでは
コピー先をフォルダー形式で書ける(末尾の \ は「このフォルダーの中へ」の意味)ことにも注目して
ください。だからこそ CopyFile はワイルドカードのコピー元と自然に組になります。とはいえ、それでも
開いているファイルはコピーできません — その制限は道具ではなく Windows に属するものだからです。
SaveCopyAs で開いているブックをコピーする — そしてコピーしてから Kill すると移動になる
生きているブックについては、答えはファイルシステムのコピーではまったくなく — ブックのメソッドです。
ThisWorkbook.SaveCopyAs "C:\Backup\March-" & Format(Now, "yyyymmdd-hhnnss") & ".xlsx"
SaveCopyAs はコピーをディスクへ書き出し、元のブックは開いたまま手つかずで残します — error 70
なし、閉じる必要なし、ブック自身のパスも変わりません。長いマクロの中で行う、正しいバックアップの
呼び出しです。Save や SaveAs と並んでブックを保存するガイドで
扱っています。
最後に、役立つ等式をひとつ。移動とは、コピーに続けて削除することです。
Name が使えないとき — たとえば Name が拒む別ドライブへの
ファイル移動 — は、コピーしてから削除する方法に頼ります。
FileCopy "C:\Reports\March.xlsx", "D:\Archive\March.xlsx" ' ドライブをまたいでコピー
Kill "C:\Reports\March.xlsx" ' それから元を削除
その Kill は永久で取り消しがありません。だからコピーが着地したことを
確認したあとにだけ実行しましょう。
正直な結論:まず「開いているか?」、次に「パターンは要るか?」で選ぶ
ファイルのコピーは、ファイルが開いているか、コピー先がすでに重要になるまでは、些細なことです。 4 つのルールがそれを正しく保ちます。
- 閉じたファイルを 1 つコピー →
FileCopy— 最短、準備なし。ただし無言で上書きするので、 既存ファイルが大事なときはコピー先をガードする。 - 多数のファイル、または本物の上書き判断 →
fso.CopyFileにワイルドカードとOverwriteフラグを添えて。 - 開いているブック →
SaveCopyAs、FileCopyは決して使わない — それがerror 70への答えの すべて。 - フルパス、既存フォルダー → コピー先ファイルを明示的に名づけ、フォルダーはまず
MkDirする。
FileCopy が error 70 を返したその瞬間、On Error に手を伸ばすのをやめて、本当の問いを立て
ましょう。このファイルは開いているか? 自分のものなら SaveCopyAs、別のものならまず閉じる。
ExcelMaster の活用
FileCopy、fso.CopyFile、SaveCopyAs の間で選び — そして最後のものだけが開いているブックに
触れられること、コピー先にはフルパスが要ること、フォルダーはまず存在していなければならないことを
覚えておくのは、「ただコピーするだけ」にしてはずいぶんな作法で、選択を間違えると実行時に
謎めいた error 70 で失敗します。
ExcelMaster は、その状況に
正しいコピーを書きます。ジョブを説明すれば — 「何かを上書きする前に、このブックをタイムスタンプ
付きでバックアップして」、あるいは「このフォルダーの全 .xlsx をアーカイブにコピーして」 — 正しい
呼び出しを生成します。生きたファイルには SaveCopyAs、バッチにはワイルドカード付きの
fso.CopyFile、フォルダーがないときの MkDir ガード、そして本当は別ドライブへの移動のつもりなら
コピーしてからの Kill。あなたは結果を説明するだけ。error 70 を
起こさない道具を選ぶのは、それがやります。
よくある質問
VBA でファイルをコピーするには?
組み込みの FileCopy source, destination を使います。両方の引数はファイル名を含むフルパスです —
たとえば FileCopy "C:\Reports\March.xlsx", "C:\Backup\March.xlsx"。参照設定はいらず、閉じたファイルを
1 つコピーしますが、コピー先を無言で上書きし、コピー先フォルダーはあらかじめ存在していなければ
なりません。多数のファイルを一度にコピーするには、ワイルドカードのコピー元を指定して
FileSystemObject.CopyFile を使います。
VBA の FileCopy が error 70 Permission denied になるのはなぜですか?
コピー元またはコピー先のファイルが開いているか、ロックされているからです。FileCopy は
排他的アクセスを必要とし、Excel は開いているブックをすべてロックします — だから実行中のブック
自身をコピーしようとすると、つねに error 70 で失敗します。たった今開いているブックをコピー
するには、代わりに ThisWorkbook.SaveCopyAs path を使いましょう。コードで開いた別のブックを
コピーするには、まず Close してから、ディスク上のファイルを FileCopy します。
VBA でファイルを別のフォルダーにコピーするには?
FileCopy に、そのフォルダー内のコピー先を、ファイル名を含むフルパスで渡します:
FileCopy "C:\In\a.xlsx", "C:\Out\a.xlsx"。コピー先フォルダーはあらかじめ存在していなければ
なりません — FileCopy は作ってくれないので、まず If Dir("C:\Out", vbDirectory) = "" Then MkDir "C:\Out"
でガードします。"C:\Out\" のようなフォルダーだけのコピー先には、FileCopy ではなく
fso.CopyFile を使いましょう。
VBA の FileCopy は既存のファイルを上書きしますか?
はい — 無言で、プロンプトもエラーもなく。これは上書きを拒む Name
ステートメントとは正反対です。既存のファイルを置き換えたくないなら、まず Dir(path) = "" か
fso.FileExists(path) でテストするか、fso.CopyFile source, destination, False を使って、既存の
コピー先が消える代わりに error 58 を発生させましょう。
VBA で現在開いているブックをコピーするには?
ThisWorkbook.SaveCopyAs "C:\Backup\copy.xlsx" を使います。SaveCopyAs はスナップショットを
ディスクへ書き出しつつ、元のブックを開いたまま変更せずに残すので、開いているファイルに FileCopy
すると出る error 70 を避けられます。長いマクロの中でタイムスタンプ付きのバックアップを取る
標準的な方法で、ブック自身の保存先パスも変えません。
検証環境
検証環境: Excel 365 (Windows 11), VBA 7.1 — 最終確認 2026-08-22。
関連ガイド: VBA Delete File · VBA Rename File · VBA Dir · VBA FileSystemObject · VBA Save Workbook
