【ExcelVBA】ファイルコピーのやり方とよくあるエラーを解説!

いつもの仕事を楽に
Sponsored Link

こんにちは、VBAエンジニアのやすこれです。

みなさんは、VBAでファイルコピーをしたことがありますか?

  • 連続でファイルコピーを行いたい
  • 多数のファイルを一気にコピーしたい
  • ファイルコピーを自動化する方法が知りたい

という方も多いのではないでしょうか。

そこで今回は、自動でファイルコピーができるFileCopyステートメントを紹介します。

Sponsored Link

VBAでファイルコピーするためのFileCopyメソッドとは?

FileCopyステートメントとは

FileCopyステートメントは、任意のファイルをフルパスで指定して、同じくフルパスで指定したコピー先にファイルをコピーできるステートメントです。

  • フルパスとは、ファイル名だけでなく、フォルダの場所まで指定したファイルアドレスのこと。

例えば画像のように「Cドライブ」の「ドキュメント」フォルダにある「Sample.xlsx」のフルパスは次のようになります。

フルパス説明
C:\ドキュメント\sample.xlsx


FileCopyステートメントの基本構文

Filecopyステートメントの基本構文とコード例を紹介します。

  1. 基本構文
FileCopy コピー元フルパス, コピー先フルパス

  1. コード例
FileCopy "C:\ドキュメント\コピー元.xlsx", "C:\ドキュメント\コピー先.xlsx"

この例では、Cドライブ内のドキュメントフォルダにある「コピー元.xlsx」を、「コピー先.xlsx」という名前で同じフォルダにコピーしています。

  • 実行前
FileCopy実行前イメージ

  • 実行後
FileCopy実行後イメージ
フルパスでの指定なので、コピー元、コピー先ともにファイル名まで指定しましょう。

また、FileCopyステートメント実行時、コピー先に同名ファイルがある場合は、無条件で上書きされるので注意しましょう。


ちなみにパスを省略した、ファイル名のみの指定でもエラーにはなりませんが、その場合カレントフォルダが指定されます。

  • カレントフォルダとは、現在使用中のフォルダのこと。

しかし、カレントフォルダは処理の中で変わることもあり、場所が保証されないので、必ずフルパスで指定しましょう。


FileCopyステートメントのエラー値と回避方法

FileCopyステートメントのエラー値

FileCopyステートメントは便利ですが、陥りがちなエラーがあります。

せっかく自動化しているマクロ処理が途中で中断されてしまえば意味がありません。

まずはよくあるエラーの例をご紹介します。

  • ファイル名が抜けている
  • コピー元のファイルが開いている
  • コピー先と同じファイルが開いている

すべて「書き込みできません。」というエラーとなります。

FileCopyステートメントエラー

エラーが起きないよう、回避方法も覚えてしまいましょう。


FileCopyステートメントエラー回避方法

ファイル名が抜けている場合は、コピー元、コピー先のファイルパスを見ればすぐに気づくかもしれません。

しかし、コピー元、コピー先を開いているときのエラーは意外と見落としがちです。

次のようにFileCopyステートメント実行前にファイルが開いているか判定し、ファイルを閉じる処理を入れておくのがおすすめです。

'コピー元のフルパスを変数copyOriginPathに代入
Dim copyOriginPath As String
copyOriginPath = ThisWorkbook.Path & "" & "コピー元.xlsx"
​
'コピー先のフルパスを変数copyTargetPathに代入
Dim copyTargetPath As String
copyTargetPath = ThisWorkbook.Path & "" & "コピー先.xlsx"
​
'コピー元、コピー先ファイルが開いていないかを確認し、開いていれば保存して閉じる
Dim wb As Workbook
For Each wb In Workbooks
 'ワークブック名が"コピー元.xlsx"または"コピー先.xlsx"の場合、保存して閉じる
    If wb.Name = "コピー元.xlsx" Then
        wb.Close SaveChanges:=True
    ElseIf wb.Name = "コピー先.xlsx" Then
        wb.Close SaveChanges:=True
    End If
Next wb
​
'コピー元、コピー先のファイルを保存して閉じたあと、FileCopy実行
FileCopy copyOriginPath, copyTargetPath


10行目から17行目の「For Each wb In Workbooks ~ Next wb」がポイントです。

開いているワークブックすべてに対してループ処理を行っています。

処理中のブックの名前「wb.Name」が「コピー元.xlsx」もしくは「コピー先.xlsx」だった場合、対象ブックを保存して閉じる処理を行っています。

このように、開いているブックとコピー元、コピー先をチェックする処理を入れることで、FileCopyステートメントがエラーになるのを回避することができます。


ExcelVBAで使えるその他のファイルコピー方法

ご紹介したFileCopyステートメントですが、コピー元、コピー先が閉じていないと使えず、使える場面は限られてきます。

ただ、コピー元、コピー先を誰かが開いているときに処理が止まってしまうと、使い勝手が良くないですよね。

そんな時におすすめなのが、「FileSystemObject」です。

「FileSystemObject」ではFileCopyステートメントでエラーになる、次の操作が可能です。

  • コピー元が開いていてもコピーできる
  • コピー元フルパスにワイルドカードを使用できる


それぞれどのように利用できるか、例をあげて順番に解説していきます。


コピー元が開いていてもコピーできる

マクロ処理中のブックを作業途中で保存

FileCopyステートメントでは、コピー元を開いているとコピーができません。

しかし実務では、マクロを実行したブックを作業途中で別ブックに保存しておきたい場面があります。

そうした場面では「FileSystemObject」が便利です。

次のサンプルコードで実際の動きを見ていきましょう。

'FileSystemObjectを生成
Dim objFSO As Object
Set objFSO = CreateObject("Scripting.FileSystemObject")
​
'ワークシート「FileSystemObject」の「A1」セルに「1」を入力し上書き保存
ThisWorkbook.Worksheets("FileSystemObject").Range("A1").Value = 1
ThisWorkbook.Save
​
'作業中のThisWorkbookを「1.xlsm」でコピー
objFSO.CopyFile ThisWorkbook.FullName, ThisWorkbook.Path & "" & "1.xlsm"
    
'ワークシート「FileSystemObject」の「A1」セルに「2」を入力し上書き保存
ThisWorkbook.Worksheets("FileSystemObject").Range("A1").Value = 2
ThisWorkbook.Save
​
'作業中のThisWorkbookを「2.xlsm」でコピー
objFSO.CopyFile ThisWorkbook.FullName, ThisWorkbook.Path & "" & "2.xlsm"
​
'FileSystemObjectを解放
Set objFSO = Nothing

まず、上記コードを実行すると下記のようにファイルがコピーされます。

  • 実行前
FileSystemObjectコピー元開いたままコピー実行前

  • 実行後
FileSystemObjectコピー元開いたままコピー実行後
順を追ってコードを解説していきます。

'FileSystemObjectを生成
Dim objFSO As Object
Set objFSO = CreateObject("Scripting.FileSystemObject")
FileSystemObjectを使う際には、まずはじめに、オブジェクトを生成する必要があります。

2~3行目の部分ですが、決まり文句なのでそのまま覚えてしまいましょう。


'ワークシート「FileSystemObject」の「A1」セルに「1」を入力し上書き保存
ThisWorkbook.Worksheets("FileSystemObject").Range("A1").Value = 1
ThisWorkbook.Save
続いて、ワークシート「FileSystemObject」の「A1」セルに「1」を入力しています。

そして、この時点での作業状態を一度上書き保存します。

  • 上書きしない、もしくは誰かが開いていて読み取り専用になっている場合は、編集内容に関わらず、最後に保存した状態でコピーされてしまいます。


'作業中のThisWorkbookを「1.xlsm」でコピー
objFSO.CopyFile ThisWorkbook.FullName, ThisWorkbook.Path & "" & "1.xlsm"
ここでは、初めに生成した「FileSystemObject」に備わっている「CopyFile」メソッドを使います。

構文は「FileCopy」ステートメントメソッドと同じです。

.CopyFile コピー元フルパス, コピー先フルパス

「ThisWorkBook.FullName」でマクロ実行ブックのフルパス、「Thisworkbook.Path」でマクロ実行ブックのパスを取得しています。

つまり、「ThisWorkbook.Path & “\” & “1.xlsm”」の部分で、マクロ実行ブックと同じフォルダ内の「1.xlsm」を表し、コピーを実行しています。


'ワークシート「FileSystemObject」の「A1」セルに「2」を入力し上書き保存
ThisWorkbook.Worksheets("FileSystemObject").Range("A1").Value = 2
ThisWorkbook.Save
これも先ほどと同じ考え方で、ワークシート「FileSystemObject」の「A1」セルに「2」を入力し、ファイルを上書き保存しています。

繰り返しになりますが、上書きしない、読み取り専用の場合は、最後に保存した状態でコピーされます。

'作業中のThisWorkbookを「2.xlsm」でコピー
objFSO.CopyFile ThisWorkbook.FullName, ThisWorkbook.Path & "" & "2.xlsm"
そして、「FileSystemObject」の「CopyFile」メソッドでマクロ実行ファイルと同じフォルダに「2.xlsm」としてコピーしています。


'FileSystemObjectを解放
Set objFSO = Nothing
最後の部分ですが、生成した「FileSystemObject」を解放しています。
このコードを実行しないと、メモリにオブジェクトが残ったままとなり、無用な負荷をかけてしまいます。

生成文と同様、決まり文句ですので、こちらも覚えてしまいましょう。


以上のコードを実行してコピーされた「1.xlsm」と「2.xlsm」の「A1」セルは画像のようになります。

  • 「1.xlsm」
1xlsm画像

  • 「2.xlsm」
2xlsm画像

このように、FileCopyステートメントと違い、コピー元が開いていてもエラーが発生しません。
これを利用して、ご紹介したようにマクロ処理途中の状態を保存することもできます。

性質の違いを理解して、上手く利用してみてください。


コピー元フルパスにワイルドカードを使用できる

大量のファイルを自動コピー

FileCopyでは、コピー元、コピー先ともにフルパスでの指定で、一つずつしかコピーが行えません。

しかし、VBAのメリットはなんといっても、手作業では難しい大量のファイル処理の自動化です。

そうした場面でも「FileSystemObject」が便利です。

次のサンプルコードで動きを見ていきましょう。

'FileSystemObjectを生成
Dim objFSO As Object
Set objFSO = CreateObject("Scripting.FileSystemObject")
     
'マクロ実行ファイルフルパス内の「.xlsm」ファイルすべてを、
'マクロ実行ファイルフルパス内の「ワイルドカードコピー」フォルダにコピー
objFSO.CopyFile ThisWorkbook.Path & "" & "*.xlsm", ThisWorkbook.Path & "" & "ワイルドカードコピー"
    
'FileSystemObjectを解放
Set objFSO = Nothing

まずは、次の画像で実行イメージを確認してみましょう。
  • 実行前
FileSystemObjectワイルドカードでコピー実行前

  • 実行後
FileSystemObjectワイルドカードでコピー実行後
コードを順に解説します。

'FileSystemObjectを生成
Dim objFSO As Object
Set objFSO = CreateObject("Scripting.FileSystemObject")
この部分でFileSystemObjectを生成しています。繰り返しとなりますが、決まり文句なので覚えてしまいましょう。


'マクロ実行ファイルフルパス内の「.xlsm」ファイルすべてを、
'マクロ実行ファイルフルパス内の「ワイルドカードコピー」フォルダにコピー
objFSO.CopyFile ThisWorkbook.Path & "" & "*.xlsm", ThisWorkbook.Path & "" & "ワイルドカードコピー"
つづくこの部分で、実際にワイルドカードを使い、ファイルをコピーしています。

まず「ThisWorkbook.Path & “” & “*.xlsm”」の部分で、マクロ実行ファイルがあるフォルダ内の拡張子「.xlsm」のファイルをすべて指定しています。

このように、ワイルドカードが使えるのは、フルパスの最終階層のみとなっていることも覚えておいてください。

そして、もう一点の注意は、コピー先でファイル名を指定せず、フォルダを指定している点です。

コピー元をワイルドカードで指定した場合は、ファイル名を指定することはできず、コピー先フォルダに元のファイル名でコピーされます。

'FileSystemObjectを解放
Set objFSO = Nothing
最後のオブジェクトの解放も、先ほど同様、決まり文句ですので、覚えてしまいましょう。


以上で、ワイルドカードで指定したファイルすべてを任意のフォルダにコピーすることができました。

手作業が難しい大量のファイルをコピーする際に使ってみてください。

VBAでのFileCopyステートメントまとめ

今回はVBAでファイルコピーができるFileCopyステートメントの使い方をご紹介いたしました。

FileCopyステートメントを使えば、自動でファイルコピーができ、使いこなせば非常に便利です。

また、今回ご紹介したエラー回避方法や、参考として解説したFileSystemObjectも理解しておくと、様々な場面で応用できるのでおすすめです。

ぜひ、使ってみてくださいね!