忍者ブログ
VBAによる実用アプリケーションの構築、およびGAS(Google Apps Script)やOffice Scriptへのモダンな移行パスを検証・解説するテックブログ。現場で即戦力となるコードモジュールや再利用可能な実用部品を継続的に提供します。

【VBA】文字化け地獄を完全解決!BOM有無・UTF-8/Shift-JISを自動判別して安全にCSVを読み込む「文字コード自動判定関数」

VBAの標準機能に「文字コードを自動判別する」スイッチはありませんが、ファイルをバイナリ(生のバイト列)として読み込み、「BOMの有無」や「UTF-8特有のバイト並びルール」を判定する自作関数を作成すれば自動判別可能です。

以下のコードをモジュールに貼り付けることで、UTF-8(BOMあり/なし)かShift-JISかを判定し、適切な文字コードでファイルを読み込めるようになります。

1. 文字コード自動判別関数

Option Explicit

' ファイルの文字コード(UTF-8 または Shift-JIS)を判定する関数
Public Function DetectEncoding(ByVal filePath As String) As String
    Dim fileNum As Integer
    Dim bytes() As Byte
    Dim fileLen As Long
    
    fileNum = FreeFile
    Open filePath For Binary Access Read As #fileNum
    fileLen = LOF(fileNum)
    
    If fileLen = 0 Then
        Close #fileNum
        DetectEncoding = "Shift-JIS"
        Exit Function
    End If
    
    ' 先頭から最大4096バイトを取得して判定
    Dim readLen As Long
    readLen = IIf(fileLen > 4096, 4096, fileLen)
    ReDim bytes(0 To readLen - 1)
    Get #fileNum, 1, bytes
    Close #fileNum
    
    ' 1. UTF-8 BOMの判定 (EF BB BF)
    If readLen >= 3 Then
        If bytes(0) = &HEF And bytes(1) = &HBB And bytes(2) = &HBF Then
            DetectEncoding = "UTF-8"
            Exit Function
        End If
    End If
    
    ' 2. BOMなしUTF-8のバイト構造チェック
    Dim i As Long
    Dim isUtf8 As Boolean
    Dim hasMultiByte As Boolean
    isUtf8 = True
    
    i = 0
    Do While i < readLen
        Dim b As Byte
        b = bytes(i)
        
        If b < &H80 Then
            ' 1バイト文字 (ASCII)
            i = i + 1
        ElseIf (b And &HE0) = &HC0 Then
            ' UTF-8 2バイト文字
            If i + 1 >= readLen Or (bytes(i + 1) And &HC0) <> &H80 Then isUtf8 = False: Exit Do
            hasMultiByte = True
            i = i + 2
        ElseIf (b And &HF0) = &HE0 Then
            ' UTF-8 3バイト文字(日本語の多くはここ)
            If i + 2 >= readLen Or (bytes(i + 1) And &HC0) <> &H80 Or (bytes(i + 2) And &HC0) <> &H80 Then isUtf8 = False: Exit Do
            hasMultiByte = True
            i = i + 3
        ElseIf (b And &HF8) = &HF0 Then
            ' UTF-8 4バイト文字(絵文字など)
            If i + 3 >= readLen Or (bytes(i + 1) And &HC0) <> &H80 Or (bytes(i + 2) And &HC0) <> &H80 Or (bytes(i + 3) And &HC0) <> &H80 Then isUtf8 = False: Exit Do
            hasMultiByte = True
            i = i + 4
        Else
            ' UTF-8のルールに違反(=Shift-JISの可能性が高い)
            isUtf8 = False
            Exit Do
        End If
    Loop
    
    If isUtf8 And hasMultiByte Then
        DetectEncoding = "UTF-8"
    Else
        DetectEncoding = "Shift-JIS"
    End If
End Function

2. 自動判別してCSVを読み込む実装例

判別した文字コードを ADODB.Stream に渡すことで、文字化けを防いで読み込めます。

Public Sub ReadCSVWithAutoDetect(ByVal filePath As String)
    Dim charSet As String
    ' 文字コードを自動判別
    charSet = DetectEncoding(filePath)
    
    Dim stream As Object
    Set stream = CreateObject("ADODB.Stream")
    
    stream.Type = 2 ' adTypeText
    stream.Charset = charSet
    stream.Open
    stream.LoadFromFile filePath
    
    ' 全文読み込み
    Dim content As String
    content = stream.ReadText(-1)
    stream.Close
    
    MsgBox "判定結果: " & charSet & vbCrLf & vbCrLf & "先頭100文字:" & vbCrLf & Left(content, 100)
End Sub

PR