UTF-8形式のテキストファイルから読み込む


本稿で紹介する「テキストファイルの操作」は、UTF-8形式のテキストファイルを対象にしています。Shift-JIS形式のファイルを扱うときは、下記ページをご覧ください。

テキストファイルを操作する

正確には「UTF-8形式のファイル」ってのも、ちょっと変な表現なんですけどね。ファイルの形式じゃなくて、そこで使われている文字コードが"UTF-8"だよってことなんですが。まぁ、細かいことはいいとして。ここでは面倒なので「UTF-8形式のファイル」「Shift-JIS形式のファイル」という呼び方をします。

UTF-8の文字コードが記録されたテキストファイルを、上記「テキストファイルを操作する」で解説した方法で読み込むと、望んだ結果になりません。ちょっと、やってみましょう。

UTF-8の文字コードで書かれたデータを読み込むときは、ADO(ActiveX Data Objects)という仕組みを使います。ADOとは何か?気になる方は、ご自身で調べてください。ADOを使って、UTF-8形式のファイルを読み込むときは、次のようにします。

Sub Sample1()
    Dim buf As String, Target As String
    Target = "D:\Work\UTF-8のテキスト.txt"
    With CreateObject("ADODB.Stream")
        .Charset = "UTF-8"
        .Open
        .LoadFromFile Target
        buf = .ReadText
        .Close
        MsgBox buf
    End With
End Sub

簡単に説明します。

CreateObject("ADODB.Stream")で、ADOを使えるようにします。

Charset = "UTF-8"というのは、UTF-8形式の文字コードでお願いします、という意味です。もちろん、UTF-8以外の文字コードを指定して読み込むことも可能です。どんな文字コードを扱えるかは、

HKEY_CLASSES_ROOT\MIME\Database\Charset

のサブキーで確認できます。↑これの意味が分からない方は、聞かなかったことにしてください。

Openは、テキストデータを操作するStreamオブジェクトを開きます。まぁ、決まり事だと思ってください。

LoadFromFile TargetでテキストファイルのデータをStreamに読み込みます。ここでは、ファイルのフルパスを変数Targetに入れて、その変数を指定していますが、もちろん「.LoadFromFile "D:\Work\UTF-8のテキスト.txt"」のように書くことも可能です。

ReadTextメソッドは、Streamからデータを読み込みます。この書き方の場合は、すべてのデータを読み込みます。上記コードでは、読み込んだデータを、変数bufに入れています。変数に入っちゃえば、こっちのもんです。あとは、どーとでもなります。

Closeで、開いたStreamを閉じます。開いたものは閉じる。人として当然ですね。

上記のように、

buf = .ReadText

とすれば、テキストファイルのすべてのデータを読み込めます。ただし、ここでちょっとした注意が必要です。ここでは、次のようなデータを読み込みました。

このデータを読み込むと、最後にひとつ改行コードが追加されて、次のようになります。

1行ずつ読み込むには

データ全部を一気に読み込むなら、上のようにすればいいです。しかし、CSVファイルのように、1行ずつ読み込みたいこともありますよね。もちろん、データ全部を読み込んだ後で、全データを改行コードで分割すれば、1行ずつの配列を作れます。次のようなCSVデータで、やってみましょうか。

Sub Sample2()
    Dim buf As String, Target As String, i As Long
    Dim tmp1 As Variant, tmp2 As Variant, j As Long
    Target = "D:\Work\UTF-8のテキスト.csv"
    With CreateObject("ADODB.Stream")
        .Charset = "UTF-8"
        .Open
        .LoadFromFile Target
        buf = .ReadText
        .Close
        tmp1 = Split(buf, vbCrLf)
        For i = 0 To UBound(tmp1)
            tmp2 = Split(tmp1(i), ",")
            j = j + 1
            Range(Cells(j, 1), Cells(j, 3)) = tmp2
        Next i
    End With
End Sub

まぁ、これでもいいんですけど、最後の方、ちょっと難しいですよね。ただでさえ、配列は苦手な人が多いです。頭の中で2つの配列をイメージするのは、簡単な作業ではありません。実は、今回のADOでも「テキストファイルを操作する」で解説したように、1行ずつ読み込むことができます。次のようにします。

Sub Sample3()
    Dim buf As String, Target As String, i As Long
    Dim tmp As Variant, j As Long
    Target = "D:\Work\UTF-8のテキスト.csv"
    With CreateObject("ADODB.Stream")
        .Charset = "UTF-8"
        .Open
        .LoadFromFile Target
        Do Until .EOS
            buf = .ReadText(-2)
            i = i + 1
            tmp = Split(buf, ",")
            For j = 0 To UBound(tmp)
                Cells(i, j + 1) = tmp(j)
            Next j
        Loop
        .Close
    End With
End Sub

データを読み込むReadTextメソッドには引数NumCharsを指定できます。すべてのデータを読み込むには「-1」を指定し、1行ずつ読み込むときは「-2」を指定します。本当はこの「-1」と「-2」には、ADOの方で定数が定義されているのですが、VBAからCreateObjectで呼び出すときは、その定数を使えません。なので実体の「-1」または「-2」を指定します。なお、引数を省略すると「-1」が指定されたものとみなします。

1行を区切るセパレーターは、標準ではWindowsで一般的に使われている改行コード「CRLF」が使われますが、「CR」や「LF」を指定することも可能です。まぁ、そのへんになると、また難しくなりますから、ここでは割愛します。

EOSプロパティは、何行目を読み込むかという、いわゆる"読み取りポイント"が、Streamの最後(End Of Stream)に到達しているかどうかを表します。VBAのEOF関数みたいなものです。