EOF関数(プロパティ)

EOF関数(プロパティ)はデータの末尾を判定するために使用します

EOF関数とは、開かれているデータの末尾を調べる関数です
データベースではプロパティとして使用されます

データが末尾に到達した時点で「True」を返します
それ以外の時点では「False」を返します

主に使用するのは、テキストデータの読み取りや、データベースデータのレコードの最終データの判定に使用します

関数の書式

引数(太字は必須引数)
(Filenumber)
戻り値の型 Integer型(Boolean型)

引数「Filenumber」はOpenステートメントで開いたときのファイル番号です

プロパティでの使用時に引数はありません

実際の使用場面

今回はよく使用するテキストデータの末尾判定処理を行います

取得を行うテキストデータ
末尾判定を行うテキストデータ

この画像のテキストデータを取得しながらEOF関数の動きを確認します

Sub 処理テスト()
Open ThisWorkbook.Path & "\新しいテキスト ドキュメント.txt" For Input As #1
    Do Until EOF(1) = True
        Debug.Print EOF(1)
        Line Input #1, 文字列変数
        Debug.Print 文字列変数
    Loop
    Debug.Print EOF(1)
Close #1
End Sub

このコードが今回作成した処理です
内容としては、テキストデータをメモリ上に読み込みモードで開き
そのファイル番号をEOF関数で「True」が返されるまで取得し続けるループ処理です

EOF関数のコード上の動き
コードの動き

画像の動きを確認してください
EOFがテキストデータの存在している場合には「False」が返されています
データが末尾に来た時点で「True」が返されてループが終了しています

この判定を行っていないと、データが存在しない状態で参照しようとしてエラーが発生します

また、ループ条件の1行に関して

    Do Until EOF(1) = True

この部分に関しては、If関数と同様に比較を行わない方法でも構いません

    Do Until EOF(1)

この様に、「=」以降は入力しなくても関数がTrueを返して条件が成り立つので必要はありません

ただ、それはある程度知識のある人が見てパッと分かるようなコーディングだと思いますのでIfステートメントにしても、自分は「= True」は省略しないようにしています

比較を行わないので、処理速度にも影響はあるようです
見やすさの方が重視するので、あまり気にしませんがねぇ

なお、テキストデータを一括で1つのデータで読み込む場合は
以下の方法も利用できます

テキストデータを1文字ずつ取得する

テキストデータから指定文字数を取得するにはInput関数を使用します。Input#ステートメントとは別物になります

'テキストデータから1文字取り出す
文字列変数 = Input(1, 1)
'テキストデータから1文字ずつ全て取り出す
Open ThisWorkbook.Path & "\新しいテキスト ドキュメント.txt" For Input As #1
Do Until EOF(1) = True
文字列変数 = Input(1, 1)
Debug.Print 文字列変数
Loop
Close #1

テキストデータから指定の文字数を取得するには「Input」関数を使用します
同じ名前のInput#ステートメントとは使い方が全く違いますので注意してください

例えば、テキストデータの文字列の文字コードを調べていきたい場合に使用できます
文字コードの取得は1文字ずつしか行えませんので、この関数で1文字ずつ取得していくことで簡単に調べることができます

関数の書式

引数(太字は必須引数)
(Number, Filenumber)
戻り値の型 String型

引数「Number」は取得する文字数です。バイト数ではなく文字数になりますので、半角も全角もどちらでも1文字は「1」になります

引数「Filenumber」はOpenステートメントで開いたファイル番号です

コード解説

文字列変数 = Input(1, 1)

関数で戻り値があるので、基本的に変数などに代入させて使用します

このコードでは、ファイル番号1の1文字を取得します
この関数をコード中で再度実行すると、次の文字が取得されます
なので、ループ処理を使用することで最後まで取得させることができます

2つ目の例コードのループ処理を以下で解説します

Open ThisWorkbook.Path & "\新しいテキスト ドキュメント.txt" For Input As #1
~~ 中略 ~~
Close #1

Openステートメントの取得モード「Input」で指定テキストファイルを開いています
この時、対象ファイルが存在しない場合は新規作成されてしまいます

Close#ステートメントで開いたデータをメモリから閉じています

Do Until EOF(1) = True
~~ 中略 ~~
Loop

テキストデータを最後まで参照するためのループ処理です

取得するテキストデータの最終データを判定するEOF関数を使用してループを行います

文字列変数 = Input(1, 1)
Debug.Print 文字列変数

ここで1文字を取得して、イミディエイトに出力しています

このループ処理のイミディエイト出力の箇所に、処理を組めばテキストデータを1文字ずつ加工していくことができます

テキストデータにデータを書き込む(Write#)

テキストデータにWrite#ステートメントで書き込みを行います。csvなどのデータとして扱う場合に使用

'テキストデータに書き込み
Write #1, "文字列", 123

Openステートメントで開いたテキストデータに書き込みを行うには「Write#」ステートメントを使用します

このステートメントはcsvデータなどの、後でデータとして扱う場合に使用します
なので、データを1行にまとめて指定する必要があります
その場合に「,」もしくは「;」を使用することでデータを結合して指定できます

引数1つ目はOpenステートメントで開いたときのファイル番号です
引数2つ目が書き込みをするデータになります

データとして書き込みをされるため、文字列の場合には「”」を含めて書き込みされます
数値は文字列ではないため、数値だけが書き込みされます

書き込みの動き

Write#ステートメントでテキストデータを書き込む場合は、csvのようなデータ群である場合が多いため、空白のテキストデータに書き込みを行います
そのため、Openステートメントで「Output」モードで既存のデータはクリアしてからデータの書き込みを行います

Open ThisWorkbook.Path & "\新しいテキスト ドキュメント.txt" For Output As #1
Write #1, "新しい追加行,白", 123
Write #1, "新しい", "追加行"; "黒", "123"
Close #1

このコードは、既存のデータがあった場合はクリアしてから2行のテキストデータを書き込みます

データの書き込みを実行した状態
実行結果

画像のテキストデータが実行結果のデータです

文字列で指定した部分は、「”」が付与されたまま書き込まれています
数値指定で書き込んだ場合はそのまま書き込みが行われます

また、「,」でも「;」でも実際に書き込まれているのは「,」になっています

空白行の追加

Write#ステートメントでは、文字列には「”」が付与されます
そのためPrint#ステートメントのように「””」と指定するとうまくいきません
何も入力しないことで空白行の指定が可能です

Write #1, "新しい追加行,白", 123
Write #1,
Write #1, "新しい", "追加行"; "黒", "123"

2行目に空白行を挿入する場合には、このコードのように2つ目の引数には何も入力しないようにします

空白がうまく挿入された状態
空白がうまく入っている状態

実行結果の画像を確認してもらうと分かりますが、2行目には何も入力されておらず、ちゃんと空白行が挿入されています

Write #1, "新しい追加行,白", 123
Write #1, ""
Write #1, "新しい", "追加行"; "黒", "123"

このコードのような状態で実行するとうまくいきません

空白がうまく入っていない状態
空白がうまく入っていない状態

画像の様に2行目が空白行とならず、「””」が入ってしまいます
空白行を挿入する場合は上記のコードのようにしてください

また、このWrite#ステートメントで書き込みをしたデータの読み込みにはInput#ステートメントを使用してください

テキストデータにデータを書き込む(Print#)

テキストデータに追記するPrint#ステートメントについて。1行の文字列を追記する場合に使用

'テキストデータの追記
Print #1, "文字列"

Openステートメントで開いたテキストデータに追記するには「Print#」ステートメントを使用します

Print#ステートメントは、csvデータのようなテキストデータはなく、文章として表示させる場合に使用します

Print#ステートメントは、コードに記載した文字列をテキストデータに書き込むので操作履歴や処理履歴などに使用することが出来ます
また、iniファイルなどの設定データをExcel外部にデータ保存する際にも使用できます

引数1つ目の「#1」はOpenステートメントで開いたときのファイル番号です
引数2つ目に追記する文字列を指定します、文字列なので「”」で囲みます

文字列の末尾には自動的に改行文字が追加されますので、ステートメントの実行前に改行文字を挿入する必要はありません

追記の動き

追記の動きの確認をするうえで重要なのが、Openステートメントでのモード選択なります
ここの設定で、既存の文字列を消去するか、それに追記していくかを選択します
ここでは、追記モードの「Append」の設定で行います

Print#ステートメント自体が文章入力の意味合いが多いので、基本的には追記モードをよく使用します

追記をするテキスト元データ
元となるテキストデータ

この画像のテキストデータに追記を行います
なお、上記にあるようにPrint#ステートメントの末尾には改行文字が付与されますが、前には挿入されません
画像を確認してもらうと分かるように、4行目に空白行が存在している状態です
この状態を前提としています

Open ThisWorkbook.Path & "\新しいテキスト ドキュメント.txt" For Append As #1
Print #1, "新しい追加行,白"
Print #1, "新しい追加行,黒"
Close #1

このコードを実行します
追記モードで開いて2行追記する処理です

追記が実行された状態のテキストデータ
コード実行結果

コードを実行すると、2行が追記されていることが確認できます
また、6行目に空白行ができていることからも改行文字がちゃんと付与されていることも確認できます

Print #1, ""

また、このコードのように追記する文字列を空白に指定することで空白行を挿入することも可能です

Print #1, "新しい追加行", "白"
Print #1, "新しい", "追加行", "黒"

このコードのようにデータを「,」で区切って複数データを一括で指定できます
ただ、Print#ステートメントの場合はうまくスペースが入らないため、基本的には「”」で囲んだ1つの文字列データを指定していきます

「,」を使って追記したときの実行結果
「,」で区切って指定した結果

コードを実行すると、この画像の様にスペースが入ってしまいます
非常に見にくくなることこの上ないので、「,」で区切るcsvデータにはWrite#ステートメントを使用してください

このPrint#ステートメントで書き込まれたデータは、LineInput#ステートメントを使用して読み込みを行います

テキストデータからデータを取得(LineInput#)

テキストデータを見た目通りに取得を行うにはLineInput#ステートメントを使用します

'テキストデータを取得
Line Input #1, 文字列変数

Openステートメントで開いたテキストデータからデータを取得するには「LineInput#」ステートメントを使用します
文章のような形でのテキストデータや、Print#ステートメントで追記したテキストデータの取得に使用します

このステートメントは改行文字までを1つのデータとして、引数の変数「文字列変数」に代入されます

改行文字とは「Cr」のこと「Lf」では分割されないため注意が必要です
なのでWindows標準の「CrLf」は分割として有効です

取得の動き

取得するテキストデータ
取得を行うテキストデータ

この画像のテキストデータをLineInput#ステートメントで文字列を取得します

Sub 処理テスト()
    Open ThisWorkbook.Path & "\新しいテキスト ドキュメント.txt" For Input As #1
    Do Until EOF(1) = True
        Line Input #1, 文字列変数
        Debug.Print 文字列変数
    Loop
    Close #1
End Sub

このコードを実行する事で取得を行います

LineInput#ステートメントでイミディエイトに出力した結果
実行結果

コードを実行した結果のイミディエイト画面の文字列です

もともとのテキストデータと見比べてみてもらうと分かるように、そのまま全てが取得されています

csvデータ特有の「,」であったり、「”」で囲む囲まないにかかわらず記号として取得しています
取得数も3行なので、3要素になっています

この動きがもう1つの取得ステートメントであるInput#ステートメントとは全く違う点です

見た目通りに取得されるので、文章として作成されているようなテキストデータの取得時に向いているステートメントです

テキストデータからデータを取得(Input#)

テキストデータからデータを取得するInput#ステートメントの使用方法。csvデータ取得に向いています

'csvやWrite#の文字列を取得
Input #1, 文字列変数

開いたテキストデータから文字列を取得するには「Input#」ステートメントを使用します
主にcsvデータやWrite#ステートメントで追記した文字列を取得する際に使用します

このステートメントでは「,」や改行でデータが区切られます
データは、引数に指定した変数に代入されます

Input #1, 文字列変数

引数1つ目の「#1」はOpenステートメントで開く際に指定したファイル番号になります
ファイル番号に関する解説は以下の記事を確認してください

2つ目の引数「文字列変数」は、取得したデータを代入する変数名を指定します
この引数はリストデータになるので、追加で指定することが可能です

取得時の動き

Sub 処理テスト()
    Open ThisWorkbook.Path & "\新しいテキスト ドキュメント.txt" For Input As #1
    Do Until EOF(1) = True
        Input #1, 文字列変数
        Debug.Print 文字列変数
    Loop
    Close #1
End Sub

1要素ずつ取得して、それをイミディエイトに出力していく処理です
このコードを以下の文字列で実行して、取得の動きを確認します

取得を行うテキストデータ
取得を行うテキストデータ

この画像のテキストデータをコード実行し、取得を行います
その取得後の出力結果が以下の画像になります

取得を実行したイミディエイトの出力結果
イミディエイトの出力結果

上下の画像を見比べて取得のされ方を確認してください

「新しいテキスト1行目,青」
これは「,」でデータが区切られるので「新しいテキスト1行目」と「青」に分割して取得されます

「”新しいテキスト2行目”,黄」
これは1つ目に取得される文字列には、「”」で囲まれた文字列表現になっています
このステートメントでは「”」は除外して中の文字列を取得します
2つ目は「,」で区切られるので上記と同じです

「”新しいテキスト3行目,赤”」
これは1行まるごと「”」で囲まれています
この状態では、「,」は文字列と認識されるのでデータが分割されることはなく1行まるごとが取得されます

Input #1, 文字列変数(0), 文字列変数(1)

このコードのように、取得させる変数を「,」で区切って追加することでまとめて取得する事が可能です
上記の「新しいテキスト1行目,青」を取得させた場合は、1回の取得で「青」までの2つを取得できます
とはいえ、分割して一括取得はSplit関数を応用するほうが簡単です

このステートメントで、取得を行う際に文字列がcsvのようにある程度きちんとしたデータではなかった場合不安定かもしれません
そういったテキストデータを扱う際には以下のLineInput#ステートメントの方がいいかもしれません

テキストデータを閉じる

Openステートメントで開かれたテキストデータはCloseステートメントで終了させます

'番号1のファイルを閉じる
Close #1
'全てのファイルを閉じる
Close

Openステートメントで開かれたテキストデータを閉じるには「Close」ステートメントを使用します

このコードを実行する事で、開いているデータが閉じられるので新規作成されていた場合はファイルが実際に作成されます

また、指定番号の使用も終了します
なのでここで終了したファイル番号は以降で同じ番号が使用できるようになります

基本的には、番号を指定して終了します
使用していない番号を指定してもエラーは発生せず、開いている分は当然終了することはありません
番号は省略が可能で、省略した場合は開かれているデータが全て終了されます

Openステートメントで開いたデータはこのコードで必ず終了するようにしてください

テキストデータを開く(書き込み用)

テキストデータをメモリ上に開くにはOpenステートメントを使用します。その時に書き込み用で開くコードと注意点

'書き込み用で開く(既存は保持される)
Open ThisWorkbook.Path & "\新しいテキスト ドキュメント.txt" For Append As #1
'書き込み用で開く(既存は消去される)
Open ThisWorkbook.Path & "\新しいテキスト ドキュメント.txt" For Output As #1

テキストファイルを開くには「Open」ステートメントを使用します
このステートメントを実行する事でメモリ上にテキストデータを展開します

ステートメントの書式

引数(太字は必須引数)
Open Pathname For Mode As # Filenumber

引数「Pathname」・「Filenumber」に関しては以下の記事で解説を行っていますので確認してください

「Mode」は開くデータの扱いに関しての指定方法です
書き込み用に開く場合は、「Append」・「Output」のどちらかを指定します

「Append」・「Output」の違いについて

どちらのキーワードを指定しても、テキストデータの書き込みが可能です
違いは既存のデータの扱いになります

Appendは既存のデータに追記していきます
Outputは既存のデータを消去して追記していきます

実際の動きをテキストデータで確認してみます

処理前のテキストデータ
処理実行前のテキストデータ

まずは、処理を実行する前のテキストデータをメモ帳で開いた状態です
この文字列にそれぞれのモードで文字列の追記を行います

Open ThisWorkbook.Path & "\新しいテキスト ドキュメント.txt" For Append As #1

Print #1, "新しい追加行,白"

Close #1

このコードでは、Appendモードでの追記を行います
追記にはPrint#ステートメントを使用します

Appendでの書き込み時のテキストデータ
Appendでの追記実行時

コード実行後のテキストデータです
もともとある3行の下にコードで追記した文字列が挿入されています

Open ThisWorkbook.Path & "\新しいテキスト ドキュメント.txt" For Output As #1

Print #1, "新しい追加行,銀"

Close #1

こちらでは、Outputモードでの追記を行います

Outputでの書き込み時のテキストデータ
Outputでの追記実行時

コード実行後のテキストデータです
こちらでは、もともとある3行のデータは消去され、コードでの追記文字列が挿入されます

新規ファイルにデータを書き込む際には、どちらのモードを使用しても構いませんが基本的には、新規時はOutput、既存に追記時はAppendをそれぞれ使用するようにします

既存テキストデータの文字形式に注意

文字化けした状態
文字化けした状態

なお、書き込み時に文字形式がANSI形式に保存されます
もともとUTFなどで保存されていた場合、Appendモードで既存の文字列の文字形式が違ってしまい、文字化けが発生します

テキストデータを開く(読み込み用)

テキストデータをメモリ上に開くにはOpenステートメントを使用します。その時に読み込み用で開くコード

'読み込み用で開く
Open ThisWorkbook.Path & "\新しいテキスト ドキュメント.txt" For Input As #1

テキストファイルやCSSデータをテキスト形式で開くには「Open」ステートメントを使用します。

このステートメントはあくまでもテキストファイルを開く動作を行うものです
この開いたデータに対して各メソッドを使用して処理を行っていきます

ステートメントの書式

引数(太字は必須引数)
Open Pathname For Mode As # Filenumber

「Pathname」はテキストデータとして開くファイルの絶対パスを指定します
単体のファイルを指定する必要がありますので、ここでワイルドカードでのファイル名指定はできません
その場合は、FileSystemObjectを使用します

また、ここで指定したファイル名のデータが存在しない場合はファイルが新規作成されます
ただ、このOpenステートメント時点では作成はメモリ上で作成されているだけです
Closeステートメントを実行する事で保存され、ファイルが作成されます

「Mode」は開くデータの扱いに関しての指定方法です
読み込み用で開く場合には「Input」を指定します

「Filenumber」はこのテキストデータの内部的なファイル番号です
1~511の整数値で番号を指定します
この番号は同時に開く場合に、重複しない番号にする必要があります
重複した番号を指定するとエラーが発生します

同時に開くことがなく、単一で処理を実行する場合は「1」を固定で使用してかまいません

この「同時に開く」というのは、OpenステートメントからCloseステートメントの間のことで、処理実行中という意味ではありません
つまり、別のファイルであっても一度Closeステートメントで閉じた後であれば番号を振り替える必要はありません

この番号は未使用番号を取得する関数がありますので、そちらに関しては以下の記事を確認してください

テキストデータを扱う

テキストデータを扱う際の操作の流れの解説と記事一覧

VBAでテキストデータを扱うには、まずテキストデータを開く必要があります
この開くという動作は、ブックを開くというアプリを起動してデータを開く方法ではなくメモリ上にデータを開きます

以降、このメモリ上でテキストデータは操作します
追記や編集、取得を行う操作を行った後、最後にテキストデータを閉じる操作を行います

テキストデータとは、文字列のみで表現されたデータのことになります
主な使用場面は、通常のテキストデータやCSVデータ、設定用にiniファイルを操作することもできます

テキストデータを扱う際の流れは以下の通りになります

  1. テキストデータを開く-Openステートメントを使用してデータを開く
  2. テキストデータの各種操作を実行する-編集・取得を行う
  3. テキストデータを閉じる

以上の操作を行い、テキストデータの形式や使用用途によって操作を分けて実行します

テキストデータを扱う際、特にcsvデータはデータサイズが特大になりがちです
このデータを操作する際には、メモリ上に展開して操作することから処理時間が異様にかかってしまうことがあります
特にループ処理時に発生しやすいので、ループ処理に組み込む際は実装前に想定以上のビッグデータでテストしてみたほうが良いです

また、テキストデータ操作はFileSystemObjectでも行うことができます
こちらは、単一のテキストファイルだけでなくフォルダ内にあるすべてのファイルを操作する時などでは合わせて実装できるので、便利ですし
コードも分かり易くて使いやすいです

ただ、本記事の操作方法は標準コードなので前準備が必要ないのが利点です

単体のテキストデータでは、本記事操作を行う
複数のテキストデータでは、FileSystemObjectを使用する

この様に使い分けると良いと思います