テキストファイルからテキストを読み込んで配列化するFunction

テキストファイルを読み込んで文字列を行ごとに配列化するFunction

テキストファイルを開いて読み込む

VBAエキスパート公式テキスト ExcelVBAスタンダードの217ページによると、

テキストファイルを開くには、Openステートメントを使います。(中略)テキストファイルを開くOpenステートメントは、これからファイルに対して読み書きを行うという承認をWindowsに対して行う命令です。

Openステートメントの書式は次の通りです。

Open ファイルのパス For 操作モード As ファイル番号

とのこと。また、テキストファイルから1行読み込むのは、同219ページによると、

Openステートメントで開いたテキストファイルから1行分のテキストを読み込む命令がLine Inputステートメントです。Line Inputステートメントの書式は次の通りです。

Line Input ファイル番号 , 変数

実行すると、テキストファイルから1行分のデータを読み込んで、変数に格納します。

とのこと。

これらを組み合わせてコーディングしてみた。

テキストファイルから指定行数分のテキストを読み込んで配列化して返すFunction

リスト1 標準モジュール
Public Function getTextFromFile( _
                  ByVal fileFullName As String, _
                  ByVal linesCount As Integer) As String()    '……(1)'
  If Dir(fileFullName) = "" Then Exit Function    '……(2)'
  Open fileFullName For Input As #1    '……(3)'
  Dim tmpArray() As String    '……(4)'
  ReDim tmpArray(linesCount)
  Dim i As Integer
  For i = 0 To linesCount - 1    '……(5)'
    If EOF(1) Then Exit For    '……(6)'
    Line Input #1, tmpArray(i)
  Next
  getTextFromFile = tmpArray    '……(7)'
  Close #1    '……(8)'
End Function

(1)の

Public Function getTextFromFile( _
                  ByVal fileFullName As String, _
                  ByVal linesCount As Integer) As String()

では、引数と返り値の指定。

第1引数は、対象のテキストファイルのフルパス、
第2引数は、読み込む行数を指定。

返り値は、文字列型の配列にしている。

たとえば、第2引数linesCountで「3」を指定すると、テキストファイルから3行分のテキストを読み込んで、要素数3の文字列型配列を返す、ということになる。

(2)の

If Dir(fileFullName) = "" Then Exit Function

はガード節。第1引数で指定したテキストファイルが存在しなかったら、すぐにfunctionを抜ける。

(3)の

Open fileFullName For Input As #1

で、指定したテキストファイルを開く。

操作モードに「Input」、ファイル番号に「#1」を指定しているので、直訳すると、

ファイルから読み込むモードでファイル番号「#1」としてテキストファイルを開けや

ぐらいだろうか。

(5)からの4行

For i = 0 To linesCount - 1
  If EOF(1) Then Exit For    '……(6)'
  Line Input #1, tmpArray(i)
Next

では、テキストファイルから1行づつ文字列を読み出して、配列変数tmpArrayにぶち込んでいく。

(6)の

If EOF(1) Then Exit For

では、EOF関数を用いてファイルの終端に達しているかどうかを調べ、ファイル終端だったらForループを抜けるようにしている。

Forループでは第2引数で指定した行数分回すことになるが、第2引数が実際の行数よりも大きかったりすると、ここで引っかかってForから抜けることになる。

(6)のチェックを通過すると、

Line Input #1, tmpArray(i)

で1行分のテキストを配列変数tmpArrayにぶち込む。

Line Inputは1回実行するごとに読み込み開始位置が次の行の先頭に移るので、

Line Input #1, 

の部分に「 i 」は出てこない。

Forループを抜けたら、必要なテキストは全て配列変数tmpArrayにぶち込み済みなので、(7)の

getTextFromFile = tmpArray

でreturnしてやる。

あとは、(8)の

Close #1

でテキストファイルを閉じる。

これについては、前掲書の218ページに

Openステートメントで開いたテキストファイルは、操作が完了したら閉じなければなりません。テキストファイルを閉じるには、Closeステートメントを使います。

とか書いてあるので、Closeステートメントの実行を忘れるとえらいことになるという感じがしますね。知らんけど。

使ってみる

次のコードで実行してみる。

スト2 標準モジュール
Public Sub testGetTextFromFile()
  Dim objDir As String
  objDir = ThisDocument.Path & "\config\"                 '"
  Dim tmpArray As Variant
  tmpArray = getTextFromFile(objDir & "config.txt", 2)    '……(1)'
  Dim i As Integer
  For i = 0 To UBound(tmpArray)    '……(2)'
    Debug.Print tmpArray(i)
  Next
End Sub

(1)の

tmpArray = getTextFromFile(objDir & "config.txt", 2)

で、リスト1のgetTextFromFileに「config.txt」のフルパスと、「2」を渡して返り値を変数tmpArrayにぶち込むようにしている。

(2)からの

For i = 0 To UBound(tmpArray)
  Debug.Print tmpArray(i)
Next

では、getTextFromFileで取得した配列の要素を順にイミディエイトに表示する。

実行結果

テキストファイル「config.txt」には、

f:id:akashi_keirin:20180124222302j:plain

こんな文字列を書き込んでおいて、このドキュメントと同じフォルダの「config」フォルダ内に保存しておく。

この状態でリスト2を実行すると、

f:id:akashi_keirin:20180124222310j:plain

ほれ、ちゃんとテキストが取得できていることがわかる。

おわりに

Excelの場合、処理に使う文字列などのデータをワークシートに持たせておくということができるが、Word(やPowerPointOutlook)の場合、そういうことができなくて不便だなあと思っていたが、このように外部ファイルにデータを持たせることで、いろいろ面白いことができるんじゃないか、と思った。

もちろん、ちょっとした設定データぐらいだったらレジストリを使うという手があるが、そこそこ大規模なデータとなるとそういうわけにもいかないと思うので……。

ちょこちょこ応用を考えることにしよう。

@akashi_keirin on Twitter