テキストファイルを一括読み込みする

FileSystemObjectを利用して、テキストファイルを一括で読み込みを行うコードについて

'FSOの宣言
Dim bhFSO As Object, bhFSOT As Object
Set bhFSO = CreateObject("Scripting.FileSystemObject")
'指定テキストファイルを開く
Set bhFSOT = bhFSO.OpenTextFile("指定テキストファイルの絶対パス")

'開いたテキストを1つのデータに一括読み込み
Dim bhTxt As String
bhTxt = bhFSOT.ReadAll

'FSOの解放
Set bhFSOT = Nothing
Set bhFSO = Nothing

テキストファイルの文字列を1つのデータに一括で読み込みをするコードです
通常VBAでテキストファイルを読み込む場合は以下のInputステートメントを利用します

ただ、このコードの場合にはデータが配列として分割されます
たとえばテキストデータ全体で検索や置換をしたい場合にそのようなデータとなった場合配列をループでまわして検証する必要が出てきてしまいます
またあえて1セルにまとめて入力したい場面も想定されます
これは新しいテキスト関数が非常に便利になったので実務上有用です

そんな場合に記事コードを利用します
このコードを利用すると文字列変数に一括でデータを読み込むことで
全体的な処理や関数処理が行いやすくなります

GetSpecialFolderメソッド

GetSpecialFolderメソッドは特殊フォルダのパスを取得するメソッドです

'ローカルのTmepフォルダパスの取得
Debug.Print bhFSO.GetSpecialFolder(2)

特殊フォルダのパスを取得するには、「GetSpecialFolder」メソッドを使用します
引数に指定する数値によって取得できるフォルダが変わります

主な使用場面は、Tempフォルダへの一時ファイルの作成やネットワーク上サーバーへのアクセス回数を減らすために一時的にローカルにファイルを保存したりする場合にも利用できます

メソッドの書式

引数(太字は必須引数)
GetSpecialFolder (folderspec)

folderspec」は取得するフォルダの種類の指定になります
必須項目で0~2のどれかを指定します

0はWindowsフォルダ、1はSystemフォルダ、2はTempフォルダをそれぞれ取得します
このメソッドはPC環境によって、絶対パスが変化する部分に動的に対応して確定したフォルダを指定することが出来ることに優位性があります

実行時バインディング全てにおいての注意点ですが、メソッドの引数には定数は使用できません
定数の設定は事前バインディングを行ったときにしか有効ではありません

指定値2は「TemporaryFolder」という定数を指定することで表現されますが、これは実行時バインディングでは使用できないので内部数値の2で指定するようにしてください

実際の使用例

実際にこのメソッドを利用する場面が多いのはTempフォルダの利用時だと思います

Tempフォルダとは、Tempファイルを保存するための専用のフォルダです
Tempファイルとは一時ファイルという、処理中に一時的にデータを退避させたり、記録しておいたりする目的で使用されます

実際別にこのフォルダを使用しなくても、処理のあるブックのパスを利用して相対的に処理する方法でも問題は無いのですが、実務として少し難点がある場合があります
それが前述した、ネットワークサーバー上にブックがある場合です

この場合にブックの保存や、同じ場所に処理で作成したファイルを大量に保存する場合などは保存のたびにサーバーとの交信を行いますので、ネットワーク状況やファイルのサイズ次第では保存待ちにより処理の冗長化が引き起こされます

その場合の解決策として、処理中はいったんローカルに保存して処理を行い
処理が完了してからブックや、処理で作成したファイルを一括でサーバーに移動させます
こうすることでサーバーとのやり取り回数を減らすことが出来るので処理を早めることが出来ます

この方法は、保存に時間がかかればかかるほど有益なので、検討してください
ちなみに、VBAの標準メソッドのブックのCopyメソッドは開いているブックに対してはエラーが発生するので、その場合はFSOのCopyメソッドを使用します

また、これに関連していますが、開いているブックをSQLで読み込みをする場合にもこの一時ファイルの作成が必要になります
ブックでSQLを利用する場合には、開いているブックを使用するとリンク切れを起こすことが多々あります
その場合には、ブックを複製してSQLを接続する必要があります
ブックのSQL操作では、削除などが行えないので複製で十分対応できると思います

FSOでは3つのフォルダを指定することが出来ますが、WScript.Shellを利用すればデスクトップなども取得可能です

IsReadyプロパティ

IsReadyプロパティは、ドライブの使用可能状態を返します。その状態を取得するコード

'Eドライブの使用可能状態を取得
Debug.Print bhFSO.GetDrive("E").IsReady

「IsReady」プロパティは、ドライブが使用可能な状態にあるかを調べるプロパティです

使用可能であれば「True」、使用不可であれば「False」が指定されます

これはUSBメモリーなどの着脱を行うドライブに対して、データのやり取りが可能な状態かを調べるのに使用します
そのため、これはドライブオブジェクトのプロパティになりますので、まずGetDriveメソッドを使用してドライブを取得します
その後、そのドライブオブジェクトのIsReadyプロパティを調べます

例コードでは1行で実行していますが、他にもドライブに対して処理を行うのであれば、GetDriveメソッドでオブジェクト変数に代入させるほうが良いです

ただ、使用状態を知りたいだけならこのコードで十分です

使用可能な状態とは、ドライブが接続されてデータの通信が可能になった状態です

ドライブを取り外す場合に、基本的には「取り外し」という操作を行います
この操作を行った段階ではまだ、物理的には取り外していません
なので、DriveExistsメソッドではTrueが返される状態です
ですがデータのやり取りは出来ない状態なので、IsReadyプロパティはFalseになります

物理的に取り外すと、DriveExistsメソッドでもFalseが返されるようになります

ドライブが存在しないときは、このプロパティを取得しようとするとエラーが発生します
つまり、DriveExistsメソッドとIsReadyプロパティの2つともがTrueを返したときにそのドライブとのデータのやり取りが可能になる、ということです

FileExists・FolderExists・DriveExistsメソッド

FileExists・FolderExists・DriveExistsメソッドは、ドライブ・フォルダ・ファイルの存在確認をするメソッドです

'ファイルの存在確認
Debug.Print bhFSO.FileExists("ファイルの絶対パス")
'フォルダの存在確認
Debug.Print bhFSO.FolderExists("フォルダの絶対パス")
'ドライブの存在確認
Debug.Print bhFSO.DriveExists("C")

FileSystemObjectを使用して、存在確認を行うメソッドです
「FileExists」メソッドはファイル
「FolderExists」メソッドはフォルダ
「DriveExists」メソッドはドライブ
それぞれの存在確認に、各メソッドを使用します

メソッドは全て、存在すれば「True」、存在しなければ「False」を返します

FileExistsメソッド

Debug.Print bhFSO.FileExists("ファイルの絶対パス")

FileExistsメソッドは、ファイルの存在確認を行うメソッドです

引数には拡張子までを含めた絶対パスを指定します
これは単体のファイルの存在確認のため、ワイルドカードは使用できません

指定の名前のファイルが存在していれば、処理を行うような場合に使用します
存在確認の中でも一番使用頻度が高いメソッドと思います

FolderExistsメソッド

Debug.Print bhFSO.FolderExists("フォルダの絶対パス")

FolderExistsメソッドは、フォルダの存在確認を行うメソッドです

引数にはフォルダ名を含む絶対パスを指定します

またパス指定であれば、ドライブの存在確認も行えます
「C:」のように「:」を付けて指定します
専用のメソッドがあるので、意味はありませんが一応可能です

フォルダは上書きされないので、あまり存在確認は必要ありません

DriveExistsメソッド

Debug.Print bhFSO.DriveExists("C")

DriveExistsメソッドは、ドライブの存在確認を行うメソッドです

引数にはドライブ名を指定します、小文字でも実行可能ですがなるべくドライブ名と同じ大文字で指定するほうがいいです

また、パスでも指定は可能です
「C:」というように指定しても確認を行えますが、メソッド的に意味はありませんので、ドライブ名で指定します

基本的には着脱されるドライブに対して使用します
USBメモリーなどのものです、これをPCで使用されているかを調べて存在すればそのドライブにデータを移動させたりする処理に使用します

なお、ドライブは存在が確認できても使用できる状態とは限りません
使用できる状態を調べるにはIsReadyプロパティを使用します

CreateFolderメソッド

CreateFolderメソッドはフォルダを作成するメソッドです。ここで作成したフォルダは変数に代入します

'フォルダを新規作成して変数に代入
Dim bhFSOFolder As Object
Set bhFSOFolder = bhFSO.CreateFolder("作成するフォルダのパス")

フォルダを作成するには「CreateFolder」メソッドを使用します

メソッドの書式

引数(太字は必須引数)
CreateFolder foldername

「foldername」は新規作成するフォルダの絶対パスです

フォルダの作成について

このメソッドは同名のフォルダを作成しようとするとエラーになります

この「フォルダを作成する」という目的であれば、わざわざFileSystemObjectを使用しなくてもMkDirステートメントで作成は可能です

ただ、この「フォルダを作成する」という目的で処理が完了することはあまり無いと思います
基本的には、フォルダを作成してそのフォルダにファイルをコピーや移動を行うといった処理に続くことになると思います
その際に、この新規作成したフォルダをオブジェクトとして取得できるFSOのほうが利便性があります

なので、フォルダの新規作成で処理が完了するならMkDirステートメント
作成してそのフォルダを扱うならCreateFolderメソッド
というような使い分けを行えばいいかなと思います

オブジェクト変数として扱うには、このメソッドの引数を「()」で囲んで代入させます
例コードの様に、変数を宣言してそこにオブジェクトとして代入させることでその新規作成したフォルダをオブジェクトとして使用が可能になります
この「bhFSOFolder」に対してメソッドやプロパティの変更を行い処理を継続します


関連の記事

DeleteFile・DeleteFolderメソッド

DeleteFile・DeleteFolderメソッドはファイル・フォルダを削除するメソッドです。フォルダの削除にはこれを使用します

'ファイルの削除(読み取り専用も削除)
bhFSO.DeleteFile "削除先のファイルパス", True
'ファイルの削除(読み取り専用があるとエラー)
bhFSO.DeleteFile "削除先のファイルパス"

DeleteFile(ファイルの削除)

'フォルダの削除(読み取り専用も削除)
bhFSO.DeleteFolder "削除先のフォルダパス", True
'フォルダの削除(読み取り専用があるとエラー)
bhFSO.DeleteFolder "削除先のフォルダパス"

DeleteFolder(フォルダの削除)

ファイルを削除するには「DeleteFile」メソッドを使用します
フォルダを削除するには「DeleteFolder」メソッドを使用します

メソッドの書式

引数(太字は必須引数)(2つのメソッドは引数が同じ)
DeleteFile filespec, force
DeleteFolder filespec, force

「filespec」は削除を実行するファイルやフォルダの絶対パスを指定します
また、この引数にはワイルドカードの使用も可能なので関連するファイル名や拡張子でまとめて削除を実行することが出来ます

「force」は読み取り専用ファイルがあった場合に削除を許可するかの設定です
省略可能で、省略した場合はFalseが指定され、削除は許可されません
許可されない設定で、削除を実行しようとするとエラーが発生します

フォルダの削除はDeleteFolderメソッドが便利

なお、DeleteFolderメソッドではフォルダの中にデータがあるかどうかは判定せず、無条件で削除が実行されます
RmDirステートメントではフォルダ内にデータがあるとエラーとなり削除は実行されませんが、こちらでは削除が実行されるので削除対象には細心の注意を払いましょう
当然ですが、削除後にデータを復旧させることはできません

削除したいフォルダにファイルやフォルダが何階層にもあるような場合、いちいち全ての階層まで下りて削除しなくてないけないRmDirステートメントですが、DeleteFolderメソッドであれば一括削除ができるので処理が簡潔になります

バックアップ処理においては特にこちらのコードの方が便利なのが分かると思います

CopyFile・CopyFolderメソッド

CopyFile・CopyFolderメソッドは、ファイルやフォルダをコピーするメソッドです

'上書きするコピー
bhFSO.CopyFile "ファイル拡張子までのパス", "コピー先のフォルダ名までのパス"
'上書きしないコピー(既存がある場合はエラー発生)
bhFSO.CopyFile "パス文字列\*.txt", "\コピー先のフォルダ名までのパス", False

CopyFile(ファイルのコピー)

'上書きするコピー
bhFSO.CopyFolder "元のフォルダパス", "コピー先のフォルダパス"
'上書きしないコピー(既存がある場合はエラー発生)
bhFSO.CopyFolder "元のフォルダパス", "コピー先のフォルダパス", False

CopyFolder(フォルダのコピー)

FileSystemObjectを使用して、フォルダをコピーするには「CopyFolder」メソッドを使用し、ファイルをコピーするには「CopyFile」メソッドを使用します

FileSystemObjectでのコピーであれば、ワイルドカードにより対象を複数にして一括で処理を行うことができます
また、フォルダのコピーに関しては、中にあるファイルも全てそのままコピーされるのでバックアップ処理にはうってつけです

メソッドの書式

引数(太字は必須引数)(2つのメソッドは引数が同じ)
CopyFile source, destination, overwrite
CopyFolder source, destination, overwrite

「source」は対象となるファイルの絶対パスを指定します、ワイルドカードの使用が出来ますので複数のファイルを一括で指定することが可能です

「destination」はコピー先のフォルダ名までの絶対パスを指定します
上記2つの引数は必須で、指定したパスが見つからない場合はエラーが発生します
特にワイルドカード使用時は注意が必要です

「overwrite」はコピー先に同名のファイルやフォルダがあった場合に上書きするかどうかの設定です。
省略可能で、省略時はTrueが指定され上書きが許可されます

ファイルは上書きされれば当然既存のものはなくなります
フォルダに関しては差分が更新される形になります

コピー元に2つのファイルがある状態で、コピー先にその2つと別のファイルがあった場合は、重複するファイルが上書きされます
重複していないファイルは削除されたりはせずそのままの状態になります

つまり、コピーしてもコピー元と全く同じファイル内容にならない可能性があるということです

完全にコピー元と同じ内容にする場合は、コピー先を一度削除してからコピーするようにします
削除にはFileSystemObjectのDeleteFolderメソッドを使用します
RmDirステートメントではフォルダ内にデータが存在すると削除が行えないのでFileSystemObjectのほうが便利です

コピーしたファイル・フォルダを変数に代入して扱う

'上書きコピーしてそのファイルを変数に代入
Dim bhFSOFile As Object
Set bhFSOFile = bhFSO.CopyFile("ファイル拡張子までのパス", "コピー先のフォルダ名までのパス")

また、コピーしたファイルやフォルダにさらに処理を続ける場合は、このメソッドを変数に代入させることで利便性が上がります
取得させる場合は、関数のように引数を「()」で囲むようにすればいいだけです

FileSystemObjectオブジェクト

FileSystemObjectの使用宣言とメソッド・プロパティ一覧

'FSOの宣言
Dim bhFSO As FileSystemObject
'Dim bhFSO As Object
Set bhFSO = CreateObject("Scripting.FileSystemObject")
'FSOの解放
Set bhFSO = Nothing

FileSystemObjectをコーディングする際には、事前バインディングが便利なので以下の記事を確認して参照設定を行ってください

コード解説

Dim bhFSO As FileSystemObject

これは事前バインディングを行うと使用できる変数の型宣言です
この変数名を使用すると、FileSystemObjectのメソッド等をインテリセンス入力が出来るようになります

'Dim bhFSO As Object

これは事前バインディングを行わなくても使用可能な汎用的な変数の型宣言です
参照設定を行わなくても使用可能なので、コーディング終了後はこちらの宣言を有効にすることで配布用にすることができます

これはコメントアウトしてありますので、先頭の「’」を消去して有効にしてください、その際に1行目の宣言に「’」を入力してコメントアウトします

Set bhFSO = CreateObject("Scripting.FileSystemObject")

このコードを実行すると、FileSystemObjectのインスタンスが作成され、使用可能な状態になります

このコードは基本的には実行時バインディングで行うものですが、最終的にこちらのコードを使用することと事前バインディング時でも使用可能なのでこのコードを使用します

Set bhFSO = Nothing

FileSystemObjectの使用が終わったらこのコードで変数の解放を行います

使用後に挿入して、必ず行ってください。

このコードが実行されるとFileSystemObjectは使用できなくなります

FileSystemObjectのメソッド

コードにより変数「bhFSO」にFileSystemObjectのインスタンスを代入しますので、以降は変数名で処理を実行していきます

オブジェクトは作成した変数を固定で使用します
便宜上、上記で宣言した変数名で以下に記載しています
(bhFSOは変数名なので、可変です)

FSOの宣言方法

FSOの基礎知識とバインディングのコード

'実行時バインディングの宣言
Dim bhFSO As Object
Set bhFSO = CreateObject("Scripting.FileSystemObject")
'事前バインディングの宣言
Dim bhFSO As FileSystemObject
Set bhFSO = New FileSystemObject

FSOとは、FileSystemObjectの頭文字を取ったものです
このFileSystemObjectとは、ファイルやフォルダを操作することに特化した機能です
(バインディングについてはこちらの記事内を確認してください)

実行時バインディングで使用する

例コードの1つ目のものは、実行時バインディングなので設定を行う必要はありません
CreateObject関数を使用して、FSOのアプリを作成します
このコードを実行するだけで、FSOの機能を使用することが出来るようになります
ですが、インテリセンス入力やオブジェクトブラウザーでのメソッドなどの確認が行えないためそれらを覚えておかないとコーディングが行えません

事前バインディングでの設定方法

上記の実行時バインディングのデメリットを解消するのが、この事前バインディングです

参照設定の開き方
参照設定の開き方

事前バインディングでは、参照設定というものを行う必要があります
参照設定は、ツールメニューの中にあります

FSOの参照設定の項目の説明
FSOの参照設定

選択すると、参照設定を設定する画面が開きます
このリストの中から「Microsoft Scripting Runtime」にチェックを付けて完了します
これで、FSOの参照設定が完了します
この操作を事前バインディングといいます、この操作を行ったPCでは例コードの2つ目のものが使用可能になります

参照設定を行った際のインテリセンス入力
インテリセンス入力ができる

事前バインディングを行うことにより、インテリセンス入力が可能になります
画像の様にリストにFSO固有の選択肢が表示されるようになるので、コーディングが非常にはかどります

FSOを使用する

ここで作成されたオブジェクト「bhFSO」に対して、処理を実行していきます
このオブジェクト自体がFSOそのものになりますので、これに対してメソッドやプロパティが存在しそれらを操作して使用します

VBA標準コードでもファイルやフォルダの操作は可能ですが、あえてこちらを使用する意味は、何よりオブジェクトとしてファイルやフォルダを操作できる点にあります

これに関しては実際に使ってみて動きを確認してもらうのがわかりやすいと思います

また出来ることの幅も大きく変わります

例えばフォルダの削除に関してですが、VBA標準ではフォルダ内にファイルが存在する場合に削除しようとするとエラーになります
削除したい場合は、中のファイルをいちいち全て削除してから行う必要がありますし、エラー処理も必要になります
FSOであれば、問答無用で削除可能です

またFSOはテキストデータの操作も行うことが出来ます
こちらもVBA標準にもありますが、FSOの方がより操作しやすいです

バインディングであったり、オブジェクト変数で扱うことなど初心者の方には理解が難しい内容かもしれませんが、この機能は使えるようになればなるほど便利さが分かるものになっています

敬遠はせずに、少し使ってみるといいですよ