LoginSignup
6
6

More than 5 years have passed since last update.

VBAで Windows APIを使った UTF-8 ←→Unicode相互変換

Last updated at Posted at 2018-05-29

VBAでUTF-8とUnicodeとの相互変換は ADODB.STREAM を使ったものがよく知られていますが、Windows APIを使った場合のやり方を記します。
Byte型の配列変数を使うので、ファイルの内容を変換する場合等には、ADODB.STREAMを使うやり方に比べて、面倒です。
ファイルとは無関係にメモリ上での相互変換をする場合には、すっきりするかもしれません。

主となる関数
Private Declare PtrSafe Function MultiByteToWideChar Lib "kernel32.dll" ( _
    ByVal CodePage As Long, _
    ByVal dwFlags As Long, _
    ByVal lpMultiByteStr As LongPtr, _
    ByVal cchMultiByte As Long, _
    ByVal lpWideCharStr As LongPtr, _
    ByVal cchWideChar As Long) As Long

Private Declare PtrSafe Function WideCharToMultiByte Lib "kernel32.dll" ( _
    ByVal CodePage As Long, _
    ByVal dwFlags As Long, _
    ByVal lpWideCharStr As LongPtr, _
    ByVal cchWideChar As Long, _
    ByVal lpMultiByteStr As LongPtr, _
    ByVal cchMultiByte As Long, _
    ByVal lpDefaultChar As LongPtr, _
    ByVal lpUsedDefaultChar As Long) As Long

Private Const CP_UTF8 As Long = 65001

'UTF8バイト配列をUnicode文字列に変換
Function FromUTF8(ByRef bData() As Byte) As String
    Dim nBufferSize As Long

    If UBound(bData) = -1 Then
        Exit Function
    End If

    nBufferSize = MultiByteToWideChar(CP_UTF8, 0, VarPtr(bData(LBound(bData))), UBound(bData) - LBound(bData) + 1, 0, 0)
    FromUTF8 = String(nBufferSize, vbNullChar)
    MultiByteToWideChar CP_UTF8, 0, VarPtr(bData(LBound(bData))), UBound(bData) - LBound(bData) + 1, StrPtr(FromUTF8), nBufferSize
End Function

'Unicode文字列をUTF8バイト配列に変換
Function ToUTF8(ByRef sData As String) As Byte()
    If Len(sData) = 0 Then
        ToUTF8 = ""
        Exit Function
    End If
    Dim nBufferSize As Long
    nBufferSize = WideCharToMultiByte(CP_UTF8, 0, StrPtr(sData), Len(sData), 0, 0, 0, 0)
    Dim Ret() As Byte
    ReDim Ret(0 To nBufferSize - 1)
    WideCharToMultiByte CP_UTF8, 0, StrPtr(sData), Len(sData), VarPtr(Ret(0)), nBufferSize, 0, 0
    ToUTF8 = Ret
End Function

以下は上記変換関数のテスト用コードです。

テストコード
Sub Main()
    Dim sUnicode As String
    Dim bUTF8() As Byte
    sUnicode = "abcあいう"

    'Unicode文字列をUTF8バイト配列に変換
    bUTF8 = ToUTF8(sUnicode)

    'UTF8バイト配列を16進数表示
    Dim sHex As String
    For i = LBound(bUTF8) To UBound(bUTF8)
        sHex = sHex & Right("0" & Hex(bUTF8(i)), 2) & " "
    Next
    Debug.Print sHex

    'UTF8バイト配列を再度Unicode文字列に変換して、表示
    Debug.Print FromUTF8(bUTF8)

End Sub

6
6
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6