VBAのファイル操作が難しい……
もっと簡潔にファイル操作を書く方法はないの?
FileSystemObjectってなんだか難しそう
こんにちは。以前勢いでExcelエキスパートを取って以来、Excelとはずいぶんと長い付き合いになりました。テックライターの平山です。
VBAで標準の関数のみを使った場合、ファイル操作は結構面倒な部類に入る操作です。読み込みが1行ずつだったり、ファイル番号の管理が面倒だったりと、あまりいいポイントがありません。
そこで、今回紹介するFileSystemObjectを利用しましょう!
FileSystemObjectは一見難しそうに見えますが、しっかり理解して使うとソースコードの記述がとても簡単になります。さらに、ファイル操作も標準機能と比べて非常に優秀なので、今までできないと諦めていたこともできるようになるかもしれません。さっそくFileSystemObjectの基本から見ていきましょう。
VBAのFileSystemObjectとは
FileSystemObject(ファイルシステムオブジェクト)はファイル・フォルダ操作専用のオブジェクトです。オブジェクトというと、慣れてない人にはウッとなってしまうポイントかもしれませんが、今回は単純に、ファイルやフォルダを入れるための入れ物と考えておきましょう。
FileSystemObjectという専用の入れ物にファイルやフォルダを入れることで、いままで苦労していた操作が簡単になるわけです。こんなイメージならそこまで嫌な感じを受けないと思うのですがいかがでしょうか?
では、FileSystemObjectを実際に使って行きましょう。FileSystemObjectは外部オブジェクトなので、利用にはひと手間必要です。
一般的に以下の2つの方法があります。
- CreateObject関数を使う方法
- 参照設定を行う方法
CreateObject関数を使う方法
CreateObject関数を使う方法は関数を利用して外部オブジェクトを呼び出す方法です。Microsoftの公式ドキュメントでもこの方法で紹介されています。
記述が簡単で、後述するバージョン違いによる問題点が発生しないというメリットがあるんですが、それ以上にVBE上でFileSystemObjectに関するインテリセンス(自動補完機能)が効かなくなる、という大きすぎるデメリットがあります。
このため、異なるバージョン間(Excel2013とExcel2017のような)でVBAアプリの受け渡しを想定する場合はこの方法を使い、そうでなければ後述の参照設定を利用するのが一般的です。では、CreateObject関数を利用する方法の具体例です。
Sub fstest() Dim fso As Object Set fso = CreateObject("Scripting.FileSystemObject") Set ts = fso.CreateTextFile("C:Samuraisamurai.txt", True) ts.WriteLine ("This is a test.") ts.Close End Sub
今回はfsoというオブジェクトにFileSystemObjectを代入しました。fsoオブジェクトにCreateTextFileメソッドを使うことで、C:Samuraiにsamurai.txtを作成し、作成したファイルをTextStream オブジェクトとしてtsに代入しています。
TextStream オブジェクトはテキストファイルそのものを表したオブジェクトと考えておけばOKでしょう。TextStream オブジェクトにはファイルポインタの位置を取得するプロパティやテキストファイルを指定した文字数だけ読み込んだり、書き込んだりするメソッドが用意されています。
テキストポインタは、テキスト入力の際に文字を入力できる場所を示す、点滅している棒状のアレをイメージしていただければ間違いではありません。仮想のアレがファイル内部を行き来して、文字を入力したり読み込んだりしているわけです。
ソースコードの解説に戻ると、tsから始まる行はテキストファイルに対する操作を表しています。WriteLineが文字の記入で、CloseがTextStreamを閉じる処理です。
コンピュータのお約束として、VBAに限らずプログラムからファイルを開いた場合は閉じる処理が必要になります。ファイル操作ではよく出てくる話ですので、合わせて覚えておいてください。CreateObject関数を利用する方法の解説は以上です。
参照設定を使う方法
一方の参照設定を使う方法をこの項で紹介していきます。参照設定について細かいところは以下の記事を参照してください。
今回必要になるのはMicrosoft Scripting Runtimeです。以下の画像のようにVBEのツールから参照設定と進んで、参照可能なライブラリファイルの中からMicrosoft Scripting Runtimeを探し出し、チェックを入れてOKを押してください。
これで参照設定ができました。この場合のサンプルが以下になります。
Sub fstest() Dim fso As New Scripting.FileSystemObject Set ts = fso.CreateTextFile("C:Samuraisamurai.txt", True) ts.WriteLine ("This is a test.") ts.Close End Sub
CreateObject関数があった行がまるまるなくなって、fsoを定義している行がObjectからNew Scripting.FileSystemObjectに変わりましたね。参照設定をすることで、FileSystemObjectを直接定義できるようになりました。
後の動作はまったく同じですので、実際に動かして確認してみてください。
FileSystemObjectと標準関数を比べてみる
前の章でFileSystemObjectがどういったものか、そして使うための前準備を行ってきました。この章ではExcelの標準関数と比べながら、FileSystemObjectがどれだけ便利かというところを見ていきます。
標準関数を使ったファイル操作に関してはこちらの記事にまとめてありますので、基本的な部分から知りたい方は是非ご覧ください。
今回はC:Samuraiにあるsamurai.txtを操作する流れを見ていきます。具体的には
- ファイルを開く
- 文字列を読み込む
- ファイルを閉じる
という操作をしていきましょう。読み込む対象のsamurai.txtは以下のように名字が列挙されているとします。
加藤
吉田
田中
大塚
石岡
木戸
標準関数のみの場合
まずは標準関数のみの場合。ファイルを開くにはOpenステートメントを使います。今回は以下のような書き方になりますね。
Open "C:Samuraisamurai.txt" For Input As #1
つづいて、文字列の読み込みです。標準関数はLine Inputを使いますが、これは1行ずつしか読み込みができないため、ループと組み合わせて読み込みを行います。また、ファイル終端への到着はEOF関数を使って判定することができ、これらを組み合わせると次のようになります。
Do Until EOF(1) Line Input #1, Name Loop
最後にファイルのクローズです。こちらは以下のようになります。
Close #1
まとめると次のようなプロシージャがかけます。
Sub filetest() Open "C:Samuraisamurai.txt" For Input As #1 Do Until EOF(1) Line Input #1, Name Loop Close #1 End Sub
FileSystemObjectを使った場合
今度はFileSystemObjectを使って今までの処理を記述してみましょう。まずはファイルを開く処理から。これはオブジェクトのインスタンス化とTextStream オブジェクトの作成に置き換えられます。具体的には以下のような記述になります。1行目がインスタンス化で、2行目がオブジェクトの作成ですね。
Dim fso As New Scripting.FileSystemObject Set ts = fso.OpenTextFile("C:Samuraisamurai.txt", ForReading)
次にファイルの中身の読み取りです。こちらはTextStream オブジェクトにReadAllメソッドが用意してあるため、次のように簡単に記述できます。
Dim Str As String Str = ts.ReadAll
最後にファイルを閉じる段階です。こちらはTextStream オブジェクトを閉じることに対応しています。
ts.Close
以上をまとめると次のような処理になります。
Sub fstest() Dim fso As New Scripting.FileSystemObject Set ts = fso.OpenTextFile("C:Samuraisamurai.txt", ForReading) Dim Str As String Str = ts.ReadAll ts.Close End Sub
今回の例では記述の長さはそこまで変わりませんでしたが、FileSystemObjectを使う方法ではメソッドによって処理の記述が簡単だったことが体験できたのではないでしょうか。
標準の関数では読み込み書き込みともに1行ずつの処理になるため、膨大な大きさのファイルを処理するには適切ですが、一般的な取り回しはそこまでよくありません。
そこで、ファイルが極端に大きい場合は標準関数をつかい、そうでない場合はFileSystemObjectを使ってメソッドで記述を簡素化するのが良い方法かと思います。
FileSystemObjectの便利なメソッドを紹介
最後にFileSystemObjectの便利なメソッドを紹介していきます。これらのメソッドが使えるようになるだけで、ファイル操作もかなり簡単に行えるようになるでしょう。以下で紹介する以外にも様々なメソッドやプロパティがあります。必要な方はリファレンスを参照にいろいろと試してみるといいでしょう。
参照:VBAリファレンス FileSystemObject
ファイル・フォルダの作成
まずはファイル・フォルダの作成です。
テキストファイルの作成 CreateTextFile(ファイル名、[[上書きの可否]、[ unicode ]])
ファイル名に作成したいファイルを絶対パスで記述します。上書きの可否はすでにファイルが存在していた場合上書きを許可するかのオプションで、booleanで記述します。省略可能なオプションで、省略した場合ファイルを上書きします。
unicode はunicodeとしてファイルを作成するか、ASCII ファイルとして作成するかを選択できるオプションです。booleanをとり、Unicodeの場合True、ASCIIの場合Falseをとります。こちらも省略可能で、省略した場合、ASCIIとみなされます。
フォルダ作成 CreateFolder(フォルダ名)
フォルダ名を絶対パスで記述します。
ファイル・フォルダのコピー
次にファイル・フォルダのコピーの仕方です。
ファイルのコピー CopyFile コピー元のファイル, コピー先, [ 上書きの可否 ]
コピー元のファイル、コピー先ともに絶対パスの文字列で記述します。コピー元のファイルについてはワイルドカード文字を利用できるので、フォルダ直下のファイルすべてをコピーといった方法も可能です。
上書きの可否はコピー先に同名のファイルが存在していた場合、上書きするかを決めるオプションです。Trueでファイルが上書きされ、Falseでは上書きされません。省略可能なオプションで、省略した場合、常に上書きされます。
フォルダのコピー CopyFolder コピー元のフォルダ, コピー先 , [ 上書きの可否 ]
コピー元のフォルダ、コピー先ともに絶対パスの文字列で記述します。コピー元がワイルドカードを使える点もファイルコピーと同様です。上書きの可否はファイルコピーと同様、上書きの可否を決めるbooleanのオプションです。既定値はTrueで省略した場合常に上書きされます。
ファイル・フォルダの削除
つづいて、ファイルとフォルダの削除についてです。
ファイルの削除 DeleteFile ファイル名, [ 強制オプション ]
ファイル名は消去したいファイルの絶対パスを文字列で記入します。ワイルドカードの利用も可能です。
強制オプションは読み取り専用属性のついたファイルを削除できるようにするためのオプションです。省略可能なオプションで既定値はFalseになります。読み取り専用属性ファイルを削除したい場合は明示的にTrueにしないと削除できません。
なお、DeleteFileメソッドは一致するファイルが存在しない場合、エラーが発生します。DeleteFileメソッドは最初にエラーが発生した時点で中止されますが、それまでに削除したファイルをもとに戻すことはできません。注意してください。
フォルダの削除 DeleteFolder フォルダ名 , [ 強制オプション ]
フォルダ名は削除したいフォルダを絶対パスの文字列で記入します。ワイルドカードが利用できる点もファイル削除と同様です。
強制オプションはファイル削除と同様に、読み取り専用フォルダを削除できるようにするためのオプションです。省略可能なオプションで既定値はFalseになります。明示的に削除したい場合のみTrueとする点もファイル削除と同様ですね。
また、DeleteFolderメソッドも一致するフォルダが見つからない場合、エラーを吐いて処理を中断します。この際、消去済みのフォルダはもとに戻せないので注意してください。
ファイル・フォルダの存在確認
次にファイルやフォルダが存在するのかを確認するメソッドを紹介します。
ファイルの存在確認 FileExists(ファイル名)
ファイル名にファイルのパスを記入します。
フォルダの存在確認 FolderExists(フォルダ名)
フォルダ名にフォルダのパスを記入します。
ファイル・フォルダの移動
最後にファイルやフォルダを移動する方法です。
Move 移動先
移動先にファイルまたはフォルダのパスを指定します。ワイルドカードを利用することはできません。
まとめ
いかがでしたか?今回はVBAのFileSystemObjectの使い方を実例を交えて見ていきました。FileSystemObjectを使えば、様々な処理がメソッドで簡単に実現できることが実感できたのでは無いかと思います。これを機に、積極的にFileSystemObjectを利用するようにしてみてください。