ファイル操作

【VBA】テキストファイルを読み書きする方法

更新日:2024/01/18

VBAでテキストファイルを読み書きする方法を紹介します。

 

テキストファイルを開く

テキストファイルを読み書きするには、最初にテキストファイルを開く必要があります。
テキストファイルを開く方法は、5つあります。

1のOpenステートメントVBAで完結している、つまりVBAで作成してVBAで読み込むテキストファイル向けです。

Openステートメントで開いたテキストファイルは、書き込み時にデータの型を判別するための加工を行ってから書き込みます。
読み込み時は、加工したデータを元のデータ型へ復元します。

そのため、テキストファイルの内容をそのまま読みとったり、文字列をそのまま書き込むことが難しい仕様となっています。
このような目的でファイルを読み書きするときは、2以降の方法で開きます。

なお現在はUTF-8ファイルでの読み書きが主流となっています。
UTF-8ファイルでの読み書きについては、次のページを読んでみてください。

 

Openステートメントでの読み書き

Openステートメントを使用すると、ファイルを開くことができます。
開く際にはファイルのパス名と、読み込み用か書き込み用かなどのモード、さらに開いた後にファイルを区別するための番号を指定します。

構文は次のようになっています。

Open pathname For mode [Access] [lock] As [#] filenumber [Len = reclength]

基本的には引数は、pathnamemodefilenumberを指定します。

  1. pathname: 開くファイルのパス
  2. mode: ファイルの使用目的。以下から選択
    Append(追記用)、Binary(バイナリモード)、Input(入力用)、Output(書き込み用)、 Random(ランダムアクセス用)
  3. access: 省略可能。許可される操作。以下から選択
    Read(読み込み)、Write(書き込み)、Read Write(読み書き)
  4. lock: 省略可能。他プロセスからのアクセス制限。以下から選択
    Shared(許可)、Lock Read(読み込みを制限)、Lock Write(書き込みを制限)、Lock Read Write(読み書きを制限)
  5. filenumber: 開いたファイルを識別する整数。ファイル番号。
    通常は1~255までの数値。他アプリケーションから同時アクセスの可能性があるときは256~511
  6. reclength: 32,767以下の整数。
    modeがRandom(ランダムアクセス)のとき、レコード長。
    その他のとき、バッファサイズ。

テキストファイルの読み書きでは、modeはAppend(追記用)、Input(入力用)、Output(書き込み用)の3つから選択します。

filenumberは数値指定もできますが、FreeFile関数を使用することで未使用の番号を自動選択できます。

FreeFile [rangenumber]

戻り値はInteger型です。
rangenumberが0または省略された時、1~255までの数値を返します。
1が指定されると、256~511までの数値を返します。

ファイルを開いたら、読み書きを行います。
方法については、使用例を参考にしてください。

最後に、Closeステートメントでファイルを閉じます。

Close [filenumberlist]

filenumberlistは省略可能です。
省略すると、Openで開いている全てのファイルが閉じられます。
また、Close 1,2,3 のように複数のファイル番号を指定できます。

 

Openステートメントの使用例

Openステートメントの使用例を紹介します。

一行単位で読み込む:Line Input #

テキストファイルの内容を一行単位で読み込むときは、Inputモードでファイルを開き、Line Input #ステートメントで読み込みます。

Line Input #filenumber , varname
  1. filenumber: Openステートメントで指定したファイル番号です。
  2. varname: 改行文字を削除した文字列が格納されます。

※Line Input #ステートメントはPrint #ステートメントで書き込まれたファイルの読み込みを想定しています。

改行文字は、vbCr(&H0d)またはvbCrLf(&H0d0a)です。
vbLf(&H0a)は改行として扱われません。

Sub lineInputTest()
    Const fileName As String = "C:\Users\xxx\Documents\text.txt"
    
    Dim fileNumber As Integer
    fileNumber = FreeFile
    
    Open fileName For Input As #fileNumber
    
    Dim LineText As String
    
    Do Until EOF(fileNumber)
        Line Input #fileNumber, LineText
        Debug.Print LineText
    Loop
    
    Close #fileNumber

End Sub

EOF関数は、ファイルの現在位置が末尾にあるときTrueを返します。
そのためEOF関数がFalseを返す間、ループを繰り返しています。

変数に値を読み込む:Input #

Write #ステートメントで書き込んだテキストファイルの内容を変数に読み込むときは、Inputモードでファイルを開き、Input #ステートメントで読み込みますします。

Input #filenumber , varlist
  1. filenumber: Openステートメントで指定したファイル番号です。
  2. varlist: 変数をカンマ区切りで羅列

varlistは、Write #ステートメントで書き込んだ順番で変数の型を合わせます。
複数回に分けて読み込むこともできます。

Sub lineInputTest()
    Const fileName As String = "C:\Users\xxx\Documents\text.txt"
    
    Dim fileNumber As Integer
    fileNumber = FreeFile
    
    Open fileName For Input As #fileNumber
    
    Dim txt As String, num As Integer, d As Date
    
    Input #fileNumber, txt, num, d

    Close #fileNumber
    
    Debug.Print txt
    Debug.Print num
    Debug.Print d

End Sub

一行単位で書き込む:Print #

テキストファイルに一行単位で書き込むときは、Outputモードでファイルを開き、Print #ステートメントで書き込みます。

Print #filenumber , outputlist
  1. filenumber: Openステートメントで指定したファイル番号です。
  2. outputlist: 出力する値
    各変数を ";" で区切って記述します。
    数値等の非文字列データは文字列に変換されます。
    Tab(n)とSpc(n)を記述できます。
    Tab(n)は左端からn桁目の文字位置を表します。タブの個数ではありません。
    Tab(n)で指定した位置が現在位置より前のときは、行替えが行われます。
    Spc(n)はn個のスペース文字を表します。

※書き込まれたファイルを読み込むときは、Line Input #ステートメントを使用します。

Sub lineInputTest()
    Const fileName As String = "C:\Users\xxx\Documents\text.txt"
    
    Dim fileNumber As Integer
    fileNumber = FreeFile
    
    Open fileName For Output As #fileNumber
    
    Dim txt As String, num As Integer, d As Date
    txt = "こんにちは"
    num = 1000
    d = Date
    
    Print #fileNumber, "123456789012345678901234567890"
    Print #fileNumber, Tab(8); txt; Tab(20); num; Spc(4); d
    Print #fileNumber, Tab(8); txt; Tab(8); num; Spc(4); d
    
    Close #fileNumber

End Sub

上記のコードで作成されたファイルは、次のような内容になっています。

123456789012345678901234567890123456789012345678901234567890
       こんにちは        1000     2023/12/18 
       こんにちは
        1000     2023/12/18 

変数の値を書き込む: Write #

ファイルの内容を変数に読み込むことを前提として変数の値をファイルに書き込むときは、Outputモードでファイルを開き、Write #ステートメントで書き込みます。

Write #filenumber , outputlist
  1. filenumber: Openステートメントで指定したファイル番号です。
  2. outputlist: 出力する値
    各変数を "," で区切って記述します。
    ※文字列にダブルクォーテーションが含まれていると、Input #ステートメントでの読み込みが正常にできません

※書き込まれたファイルを読み込むときは、Input #ステートメントを使用します。

Sub lineInputTest()
    Const fileName As String = "C:\Users\xxx\Documents\text.txt"
    
    Dim fileNumber As Integer
    fileNumber = FreeFile
    
    Open fileName For Output As #fileNumber
    
    Dim txt As String, num As Integer, d As Date
    txt = "こんにちは"
    num = 1000
    d = Date
    
    Write #fileNumber, txt, num, d
 
    Close #fileNumber

End Sub

書き込まれたデータは型ごとに、元の型が判別できるような形式で書き込まれます。
上記のコードで作成されたファイルは、次のような内容になっています。

"こんにちは",1000,#2023-12-18#

文字列にダブルクォーテーションが含まれていると、次のようにダブルクォーテーションが二つ出力されます。

書き込む文字列: "こんにちは"A"さん"
ファイル内容: "こんにちは""A""さん"

Input #ステートメントで読み込むと3つの文字列として解釈されます。

 

FileSystemObject.OpenTextFileメソッド

OpenTextFileメソッドは、FileSystemObjectオブジェクトのメソッドです。
既存ファイルの読み込み、書き込み、追記を行うTextStreamオブジェクトを返しますが、ファイルが存在しないとき作成することもできます。

FileSystemObjectオブジェクト.OpenTextFile (FileName , [ IOMode ], [ Create ], [ Format ])
  1. FileName : ファイルのパス
  2. IOMode : 省略可能。ファイルのモードをIOMode列挙型で指定。規定値はForReading
    ■IOMode列挙型
    定数意味
    ForAppendin8追記
    ForReading1読み込み
    ForWriting2書き込み
  3. Create : 省略可能。ファイルが存在しないとき作成するかどうか。規定値はFalse(作成しない)
  4. Format : 省略可能。ファイルの文字コードをTristate列挙型で指定。規定値はTristateFalse
    ■Tristate列挙型
    定数意味
    TristateFalse0Ascii形式
    TristateMixed-2混在形式
    TristateTrue-1Unicode形式(UTF-16)
    TristateUseDefault-2システムの既定の設定

formatのTristateMixedは意味合いがあいまいですが、TristateUseDefaultと同じ値なので、システムの既定の設定を使用すると解釈しておけばOKです。
またTristateFalseとTristateUseDefaultは、日本語環境ではシフトJISです。

次のコードはFileSystemObjectを取得後にテキストファイルを開き、内容を変数に読み込んでいます。

Sub openTextFileSample()
    Const fileName As String = "C:\Users\xxxx\Documents\text.txt"
    
    Dim fso As New Scripting.FileSystemObject
    Dim stream As TextStream
    Set stream = fso.OpenTextFile(fileName)
    
    Dim textData As String
    With stream
        textData = .ReadAll
        .Close
    End With
    Debug.Print textData
End Sub

読み込みはTextStreamオブジェクトで行っています。
TextStreamオブジェクトについては、このページのTextStreamオブジェクトを参照してください。

 

FileSystemObject.CreateTextFileメソッド

CreateTextFileメソッドは、FileSystemObjectオブジェクトのメソッドです。
ファイルを新規作成後に、TextStreamオブジェクトを返します。

FileSystemObjectオブジェクト.CreateTextFile(FileName , [ Overwrite ], [ Unicode ])
  1. FileName : ファイルのパス
  2. Overwrite : 省略可能。既存ファイルを上書きするかどうか。規定値はTrue(上書きする)
  3. Unicode : 省略可能。文字コードをUnicode(UTF-16)で開くかどうか。規定値はFalse(ASCIIで開く)

次のコードはFileSystemObjectを取得後にテキストファイル新規作成して、変数の内容をファイルに書き込んでいます。

Sub CreateTextFileSample()
    Const fileName As String = "C:\Users\xxxx\Documents\text.txt"
    
    Dim fso As New Scripting.FileSystemObject
    Dim stream As TextStream
    Set stream = fso.CreateTextFile(fileName)
    
    Dim textData As String
    textData = "書き込みテスト"
    
    With stream
        .Write textData
        .Close
    End With
End Sub

TextStreamオブジェクトについては、このページのTextStreamオブジェクトを参照してください。

 

File.OpenAsTextStreamメソッド

OpenAsTextStreamメソッドはFileSystemObjectのGetFileメソッドで取得されるFileオブジェクトのメソッドです。
OpenAsTextStreamメソッドを実行すると、Fileオブジェクトに関連付けられているファイルを開き、開いたファイルを操作するTextStreamオブジェクトを返します。

Fileオブジェクト.OpenAsTextStream( [ IOMode ], [ Format ] )
  1. IOMode : 省略可能。ファイルのモードをIOMode列挙型で指定。規定値はForReading
  2. Format : 省略可能。ファイルの文字コードをTristate列挙型で指定。規定値はTristateFalse

次のコードはFILEオブジェクトを取得後にテキストストリームを開き、内容を変数に読み込んでいます。

Sub openTextFileSample()
    Const fileName As String = "C:\Users\xxxx\Documents\text.txt"
    
    Dim fso As New Scripting.FileSystemObject
    Dim fileObj As FILE
    Set fileObj = fso.GetFile(fileName)
    
    Dim stream As TextStream
    Set stream = fileObj.OpenAsTextStream()
    
    Dim textData As String
    With stream
        textData = .ReadAll
        .Close
    End With
    Debug.Print textData
End Sub

TextStreamオブジェクトについては、このページのTextStreamオブジェクトを参照してください。

 

Folder.CreateTextFileメソッド

CreateTextFileメソッドはFileSystemObjectのGetFolderメソッドで取得されるFolderオブジェクトのメソッドです。
CreateTextFileメソッドを実行すると、Folderオブジェクトに関連付けられているフォルダ内に新規ファイルを作成してファイルを開き、開いたファイルを操作するTextStreamオブジェクトを返します。

Folderオブジェクト.CreateTextFile(FileName , [ Overwrite ], [ Unicode ])
  1. FileName : ファイルの名前
  2. Overwrite : 省略可能。既存ファイルを上書きするかどうか。規定値はTrue(上書きする)
  3. Unicode : 省略可能。文字コードをUnicode(UTF-16)で開くかどうか。規定値はFalse(ASCIIで開く)

次のコードはFolderオブジェクトを取得後にテキストファイル新規作成して、変数の内容をファイルに書き込んでいます。

Sub CreateTextFileSample()
    Const folderName As String = "text.txt"
    Const fileName As String = "C:\Users\xxxx\Documents\"
    
    Dim fso As New Scripting.FileSystemObject
    Dim folderObj As folder
    Set folderObj = fso.GetFolder(folderName)
    
    Dim stream As TextStream
    Set stream = folderObj.CreateTextFile(fileName)
    
    Dim textData As String
    textData = "書き込みテスト2"
    
    With stream
        .Write textData
        .Close
    End With
End Sub

TextStreamオブジェクトについては、このページのTextStreamオブジェクトを参照してください。

 

TextStreamオブジェクト

TextStreamオブジェクトは、ファイルの読み書きを行うメソッドをメンバーに持つオブジェクトです。
FileSystemObjectオブジェクトのOpenTextFileメソッドとCreateTextFileメソッド、FileオブジェクトのOpenAsTextStreamメソッド、FolderオブジェクトのCreateTextFileメソッドで取得できます。

メソッド

TextStreamオブジェクトは、次のメソッドを持っています。

メソッド名内容使用例
CloseTextStreamオブジェクトを閉じる---
Read指定文字数を読み込む文字数単位での読み込み例
ReadAll全て読み込む一括読み込み例
ReadLine1行読み込む1行単位での読み込み例
Skip指定文字数を読み飛ばす文字数単位での読み込み例
SkipLine1行読み飛ばす1行単位での読み込み例
Write文字列を書き込む書き込み例
WriteBlankLines改行文字を書き込む書き込み例
WriteLine文字列と改行を書き込む1行単位での書き込み例

プロパティ

TextStreamオブジェクトは、次のプロパティを持っています。

プロパティ名内容使用例
AtEndOfLine現在位置が行末かどうか1行単位での読み込み例
AtEndOfStream現在位置が末尾かどうか文字数単位での読み込み例
Column改行文字からの現在位置(1から)文字数単位での読み込み例
Line現在の行番号(1から)1行単位での読み込み例

 

TextStreamオブジェクト使用例

次のテキストファイルの読み込み例、または書き込みでの生成例を紹介します。
改行は、vbCrLfです。

1234567890[CR][LF]
1234567890[CR][LF]
1234567890[CR][LF]
1234567890[CR][LF]
1234567890[CR][LF]

一括読み込み例

ファイルの内容を一括で読み込むときは、ReadAllメソッドを使用します。

Sub readAllSample()
    Const fileName As String = "C:\Users\xxxx\Documents\text.txt"
    
    Dim fso As New Scripting.FileSystemObject
    Dim stream As TextStream
    Set stream = fso.OpenTextFile(fileName)
    
    Dim textData As String
    With stream
        textData = .ReadAll
        .Close
    End With
    Debug.Print textData
End Sub

実行すると、ファイルの内容がそのままイミディエイトウィンドウに表示されます。

1234567890
1234567890
1234567890
1234567890
1234567890

文字数単位での読み込み例

文字数単位で読み込むときは、Readメソッドを使用します。
読み飛ばすときは、Skipメソッドを使用します。
最後まで読み込んだかどうかの判定は、AtEndOfStreamプロパティで行います。
また、Columnプロパティで先頭、または改行からの位置を確認できます。

次の例は現在位置を表示後、3文字読み込み、3文字読み飛ばしを繰り返しています。

Sub readSample()
    Const fileName As String = "C:\Users\xxxx\Documents\text.txt"
    
    Dim fso As New Scripting.FileSystemObject
    Dim stream As TextStream
    Set stream = fso.OpenTextFile(fileName)
    
    Dim textData As String
    Debug.Print "********Start"    
    With stream
        Do Until .AtEndOfStream
            Debug.Print "現在位置:" & .Column
            textData = .Read(3)
            Debug.Print ">" & textData
            If Not .AtEndOfStream Then .Skip (3)
        Loop
        .Close
    End With
    Debug.Print "********End"
End Sub

ストリームの最後まで読み取った時点でSkipメソッドを実行するとエラーになります。
そこで、AtEndOfStreamプロパティを参照してからSkipメソッドを実行しています。

コードを実行すると、次のような内容がイミディエイトウィンドウに表示されます。

********Start
現在位置:1
>123
現在位置:7
>789
現在位置:2
>234
現在位置:8
>89

現在位置:3
>345
現在位置:9
>9

現在位置:4
>456
現在位置:10
>
1
現在位置:5
>567
現在位置:11
>

********End

改行はvbCrLfなので2文字として扱われます。
空欄の行は改行コードで改行されています。

1行単位での読み込み例

1行単位で読み込むときは、ReadLineメソッドを使用します。
1行単位で読み飛ばすときは、SkipLineメソッドを使用します。

行末のコードはドキュメント等に明確な記述がありません。
動作確認したところ、vbLf(&H0a)とvbCrLf(&H0d0a)を改行コードとして認識していました。
Line Input #は vbCr(&H0d)とvbCrLf(&H0d0a)を改行コードとして認識します。
そのため改行コードがvbLfまたはvbCrのテキストファイルは、Line Input #で読み込めてもReadLineメソッドで読み込めない、またはその逆という現象がおきるので注意が必要です。

最後まで読み込んだかどうかの判定は、AtEndOfLineプロパティで行います。
また、Lineプロパティで現在の行番号を確認できます。

次の例は現在の行番号を表示後、1行読み込み、1行読み飛ばしを繰り返しています。

Sub readSample()
    Const fileName As String = "C:\Users\xxxx\Documents\text.txt"
 
    Dim fso As New Scripting.FileSystemObject
    Dim stream As TextStream
    Set stream = fso.OpenTextFile(fileName)
    
    Dim textData As String
    Debug.Print "********Start"
    With stream
        Do Until .AtEndOfLine
            Debug.Print "現在行:" & .Line
            textData = .ReadLine
            Debug.Print ">" & textData
            If Not .AtEndOfLine Then .SkipLine
        Loop
        .Close
    End With
    Debug.Print "********End"
End Sub

最終行まで読み取った時点でSkipLineメソッドを実行するとエラーになります。
そこで、AtEndOfLineプロパティを参照してからSkipLineメソッドを実行しています。

コードを実行すると、次のような内容がイミディエイトウィンドウに表示されます。

********Start
現在行:1
>123456789
現在行:3
>123456789
現在行:5
>123456789
********End

書き込み例

ファイルに書き込むときは、まずはTextStreamオブジェクトをForWritingモードで開きます。

Writeメソッドで文字列を書き込みます。
WriteBlankLines(n)メソッドで、n個の改行コードを書き込むことができます。
書き込まれる改行コードはドキュメント上に明確な記述がありません。

Sub writeSample()
    Const fileName As String = "C:\Users\xxxx\Documents\text.txt"
   
    Dim fso As New Scripting.FileSystemObject
    Dim stream As TextStream
    Set stream = fso.OpenTextFile(fileName, ForWriting)
    
    Dim textData As String
    textData = "1234567890"

    Dim i As Integer
    With stream
        For i = 0 To 4
            .Write textData
            .WriteBlankLines 1
        Next
        .Close
    End With
    
End Sub

作成されたテキストファイルは、次のような内容になっています。

1234567890
1234567890
1234567890
1234567890
1234567890

改行コードは、vbCrLf(&H0a0d)が書き込まれていました。

1行単位での書き込み例

1行単位でファイルに書き込むときは、まずはTextStreamオブジェクトをForWritingモードで開きます。

WriteLineメソッドで文字列を書き込むと直後に改行コードが書き込まれます。
WriteメソッドとWriteBlankLines(1)と同じ結果になります。

書き込まれる改行コードはドキュメント上に明確な記述がありません。

Sub writeSample()
    Const fileName As String = "C:\Users\xxxx\Documents\text.txt"
   
    Dim fso As New Scripting.FileSystemObject
    Dim stream As TextStream
    Set stream = fso.OpenTextFile(fileName, ForWriting)
    
    Dim textData As String
    textData = "1234567890"

    Dim i As Integer
    With stream
        For i = 0 To 4
            .WriteLine textData
        Next
        .Close
    End With
    
End Sub

作成されたテキストファイルは、次のような内容になっています。

1234567890
1234567890
1234567890
1234567890
1234567890

改行コードは、vbCrLf(&H0a0d)が書き込まれていました。

更新日:2024/01/18

書いた人(管理人):けーちゃん

スポンサーリンク

記事の内容について

null

こんにちはけーちゃんです。
説明するのって難しいですね。

「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。

裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。
そんなときは、ご意見もらえたら嬉しいです。

掲載コードについては事前に動作確認をしていますが、貼り付け後に体裁を整えるなどをした結果動作しないものになっていることがあります。
生暖かい視線でスルーするか、ご指摘ください。

ご意見、ご指摘はこちら。
https://note.affi-sapo-sv.com/info.php

 

このサイトは、リンクフリーです。大歓迎です。