きなこSHOW

自作プログラム置き場です。

Access VBAでUTF-8のCSVデータを文字化けせずにインポートするサンプル

Access VBAでUTF-8のCSVファイルをインポートする機会がありまして、そんなの以前作ったよな、と実行してみると、日本語が文字化けしてる!!
文字化けしてる!
AccessでUTF-8データをインポートするにはもうひと工夫必要でした。
コピーしてそのまま使えるサンプルを作成しましたのでご査収ください。

システムで生成されたデータがUTF-8だったというケースには多く直面します。
Accessで扱うデータの文字コードはShift-JISなので、Shift-JISのデータであれば普通に取り込んで正しく表示することができますが、UTF-8のデータを取り込むと日本語が正しく表示されません。
もはやUTF-8が主流なので、Access側で文字化けを防ぐ工夫をしてやるのが手っ取り早い方法です。
やだなにこれ!
文字化けを防ぐ方法として「ADODB.Stream」オブジェクトを使用して取り込む際に文字コードを設定してやる事で、UTF-8でも文字化けせずにインポートを実現できます。

文字コードがUTF-8のCSVデータをインポートするコード

サンプルコード

参照設定は「Microsoft Active Data Object x.x Library」にチェックを付けてください。
「ADODB.Stream」オブジェクトはCreateObjectで生成しているので、参照設定は不要です。
事前バインディングと実行時バインディングが混在しているのが気持ち悪い方は、各自で統一してください。

Public Function FncImportCsv(ByVal strPath As String, _
                             ByVal strTable As String, _
                             Optional ByRef strMessage As String = "") As Boolean
On Error GoTo Err_Sec
    Dim bRet As Boolean: bRet = False
    Dim strLine As String
    Dim arrLine As Variant
    Dim arrFields() As String
    Dim i As Long, j As Long
    
    Dim adoSt As Object
    'ADODB.Streamオブジェクトのインスタンスを生成
    Set adoSt = CreateObject("ADODB.Stream")
    
    Dim adoRs As New ADODB.Recordset
    'ADODB.Recordsetオブジェクトのインスタンスを生成
    adoRs.Open strTable, CurrentProject.Connection, , adLockOptimistic
    
    i = 0
    With adoSt
        .Charset = "UTF-8"          'StreamのCharsetを"utf-8"に設定する
        .Open                       'StreamをOpen
        .LoadFromFile (strPath)     'ファイルからStreamオブジェクト変数にデータを読み込み
        
        Do Until .EOS               'Streamの末尾まで繰り返す
        
            strLine = .ReadText(adReadLine) 'Streamから1行取り込み
            
            If i = 0 Then
                arrFields = Split(strLine, ",", , vbTextCompare)    'カンマで分割してフィールド名用の配列に格納
            Else
                arrLine = Split(Replace(strLine, """", ""), ",", , vbTextCompare)   'カンマで分割してデータ用の配列に格納
                adoRs.AddNew        'Recordsetに1行追加する
                For j = 0 To UBound(arrFields)
                    adoRs.Fields(arrFields(j)) = arrLine(j)    '読み込んで分割したデータをフィールドに格納する
                Next j
                adoRs.Update        'Recordsetの更新内容を反映する
            End If
            i = i + 1
        Loop
        adoRs.Close
        .Close
    End With
    
    Debug.Print "Record Count:", CStr(i)
    
    bRet = True
    
Exit_Sec:
On Error Resume Next

    Set adoRs = Nothing
    Set adoSt = Nothing
    
    FncImportCsv = bRet
    
    Exit Function

Err_Sec:
    strMessage = "ErrNo : " & Err.Number & ": ErrDescription : " & Err.Description
    'Call sOutputLog("FncImportCsv: " & strMessage) '(エラーログ出力)
    Resume Exit_Sec
End Function

このCSVの条件として、先頭行にカンマ区切りでフィールド見出しを持ち、インポート先テーブルのフィールド名と同一である事と、数値桁のカンマ区切りは除去された状態になっている事が前提です。2点についてご注意ください。

「FncImportCsv」プロシージャの引数は3つ。
それぞれ次の意味の値をセット/リターンします。
第1引数:インポート対象となるCSVファイルのフルパスを記述。
第2引数:Accessのテーブル名を指定。
第3引数:当プロシージャでエラーが発生した場合、エラー番号とDescriptionをセットします。呼び出し元に返却することができます。

「Err_Sec:」のブロック内にコメントアウトで記載した「Call sOutputLog(...)」は、エラーの内容をテキストファイルに出力するプロシージャを呼び出しています。
必要に応じてコメントアウトを外してください。
「sOutputLog」プロシージャは以下の記事で紹介しています。

kinaccco.hatenadiary.com

 

呼び出し例

上記コードを呼び出す方のコードは、次のように記述します。

    Dim strMessage As String
    If Not FncImportCsv("c:\data\utf8data.csv", "t_test", strMessage) Then 
        MsgBox(strMessage)
    End If

実行してみると、CSV1行目のフィールド名に合致するフィールドにデータが正しくインポートされて、日本語が正しく表示されている事が確認できたと思います。
Streamを使用しているからか、よほどの大量データでもない限り実行速度はそれほど気にならない程度でしょう。

 

参考

文字コードがShift-JISのCSVデータをインポートするには

ちなみに、Shift-JIS形式のテキストをインポートする方法として、こちらの記事でサンプルコードを紹介しています。

kinaccco.hatenadiary.com

文字コードの指定ができないため、UTF-8の場合上のSQL文でインポートする方法を使う事ができず、今回「ADODB.Stream」の使用となりましたが、個人的にはSQL好きなのでAccessからSQLを発行する際にも文字コード設定が可能になったらいいのになぁ、とちょっと思っています。