サイトについて      連絡先   検索

VBA Unicode 文字の入力や変換、読み込みについて

はじめに

Excel VBA Unicode 文字の入力や変換、読み込みの方法を紹介します。

ChrW 関数」を使用して入力できます。Shift_JIS に存在しない文字は ? に文字化けしているように見えますが入力できます。ただし、「𩸽」や「😃」のようなサロゲートペア文字を扱うためには、関数を作成する必要があります。

UTF-8 や UTF-16 のファイルを読み込む方法も紹介します。

  • 目次
    • VBA の Unicode 対応状況
    • 変換する
    • 入力する
    • 判定する
    • 列挙する
    • ファイルの読み書き
    • 表示する

VBA の Unicode 対応状況

VBA の文字コードは Unicode (UTF-16) です。しかし、入力や表示できる文字は Shift_JIS の文字だけです。そのため、Shift_JIS に存在しない Unicode 文字は直接入力や表示はできません。?になります。

Excel は Unicode 文字を入力も表示もできます。

サロゲートペア文字は上位と下位の 2 文字として扱われます。

変換する

VBA の文字コードは Unicode (UTF-16) なのですべての文字が 2 バイトです。


Dim i As Integer

i = LenB("ABC")
Debug.Print (i) ' 6, UTF-16

i = LenB("ABC")
Debug.Print (i) ' 6, UTF-16

StrConv 関数」を使用して Shift_JIS に変換できます。


Dim s As String
Dim i As Integer

s = StrConv("ABC", vbFromUnicode) ' UTF-16 を Shift_JIS に変換
i = LenB(s)
Debug.Print (i) ' 3, Shift_JIS
       
s = StrConv("ABC", vbFromUnicode) ' UTF-16 を Shift_JIS に変換
i = LenB(s)
Debug.Print (i) ' 6, Shift_JIS

同じように「StrConv 関数」を使用して、Shift_JIS に変換したものを Unicode に戻せます。


Dim s As String
Dim i As Integer

s = StrConv("ABC", vbFromUnicode) ' UTF-16 を Shift_JIS に変換
s = StrConv(s, vbUnicode)         ' Shift_JIS を UTF-16 に変換
i = LenB(s)
Debug.Print (i) ' 6, UTF-16
       
s = StrConv("ABC", vbFromUnicode) ' UTF-16 を Shift_JIS に変換
s = StrConv(s, vbUnicode)            ' Shift_JIS を UTF-16 に変換
i = LenB(s)
Debug.Print (i) ' 6, UTF-16

入力する

VBA に Shift_JIS に存在しない Unicode 文字などを入力すると?に文字化けします。これは実際に?を入力したのと同じです。サロゲートペア文字𩸽😃などを入力すると??に文字化けします。


Dim s As String
s = "?"  ' 頰
s = "??" ' 𩸽
s = "??" ' 😃

エクセル UNICHAR 関数:Unicode を文字に変換する」を使用して Unicode 文字を入力できます。


Range("A1").Value = WorksheetFunction.Unichar(38960)   ' 頰
Range("A1").Value = WorksheetFunction.Unichar(&H9830)  ' 頰, エラー Integer になるため
Range("A1").Value = WorksheetFunction.Unichar(&H9830&) ' 頰, 末尾に & を付けて Long にする

Range("A2").Value = WorksheetFunction.Unichar(171581)  ' 𩸽
Range("A2").Value = WorksheetFunction.Unichar(&H29E3D) ' 𩸽

Range("A3").Value = WorksheetFunction.Unichar(128515)  ' 😃
Range("A3").Value = WorksheetFunction.Unichar(&H1F603) ' 😃
VBA で 16 進数を入力するには&H3042のように&Hを頭に付けます。

エクセル UNICODE 関数:文字の Unicode を取得する」を使用して文字の Unicode を取得できます。


Dim s As String
Dim d As Double
       
s = WorksheetFunction.Unichar(38960)' 頰
d = WorksheetFunction.Unicode(s)
Debug.Print (d) ' 38960

s = WorksheetFunction.Unichar(171581)' 𩸽
d = WorksheetFunction.Unicode(s)
Debug.Print (d) ' 171581

s = WorksheetFunction.Unichar(128515)' 😃
d = WorksheetFunction.Unicode(s)
Debug.Print (d) ' 128515

VBA の「ChrW 関数」を使用しても Unicode の文字を入力できます。ただしサロゲートペア文字を入力するには上位と下位の文字を結合する必要があります。


Range("A1").Value = ChrW(-26576) ' 頰, Integer
Range("A1").Value = ChrW(38960)  ' 頰, Long
Range("A1").Value = ChrW(&H9830) ' 頰, 16 進数

Range("A2").Value = ChrW(-10137) & ChrW(-8643) ' 𩸽, Integer

サロゲートペア文字の上位と下位の Unicode を取得するには、「Mid 関数」でそれぞれの文字を取得して「AscW 関数」で文字コードを取得します。サロゲートペア文字は 2 文字として扱われます。


Dim s As String
s = WorksheetFunction.Unichar(171581) ' 𩸽

Dim high As Integer ' 上位コード
Dim low As Integer  ' 下位コード
high = AscW(Mid(s, 1, 1))
low = AscW(Mid(s, 2, 1))
Debug.Print (high) ' -10137
Debug.Print (low)  ' -8643

Range("A1").Value = ChrW(high) & ChrW(low) ' 𩸽
AscW 関数」の戻り値が Integer なので負の値になるときがあります。これを Long として常に正の値にするには CUInt 関数を作成して変換できます。詳しくは「AscW 関数」のページをご覧ください。

判定する

サロゲートペア文字か判定するための関数を作成します。

IsSurrogate 関数に判定したい文字列を渡して、その最初の文字がサロゲートペア文字か判定します。True ならサロゲートペア文字です。

IsHighSurrogate 関数に「AscW 関数」で取得した文字コードを渡して、上位コードか判定します。

IsLowSurrogate 関数に「AscW 関数」で取得した文字コードを渡して、下位コードか判定します。


Sub 実行()
    Dim s As String
    Dim b As Boolean
    
    s = WorksheetFunction.Unichar(38960)  ' 頰
    b = IsSurrogate(s)
    Debug.Print (d) ' False

    s = WorksheetFunction.Unichar(171581) ' 𩸽
    b = IsSurrogate(s)
    Debug.Print (b) ' True
    
    s = WorksheetFunction.Unichar(128515) ' 😃
    b = IsSurrogate(s)
    Debug.Print (b) ' True
    
    s = "あ"
    b = IsSurrogate(s)
    Debug.Print (b) ' False
End Sub
  
' 指定した文字列の最初の文字がサロゲートペア文字かどうか
Function IsSurrogate(ByVal text As String) As Boolean
    ' 1 文字ならサロゲートペアではない
    If Len(text) <= 1 Then
        IsSurrogate = False
        Exit Function
    End If
    
    ' 上位を取得
    Dim high As Integer
    high = AscW(Mid(text, 1, 1))
    
    Dim isHigh As Boolean
    isHigh = IsHighSurrogate(high)
    
    ' 下位を取得
    Dim low As Integer
    low = AscW(Mid(text, 2, 1))
    
    Dim isLow As Boolean
    isLow = IsLowSurrogate(low)
    
    ' サロゲートペア
    IsSurrogate = (isHigh And isLow)
End Function
  
' 指定した文字コードがサロゲートの上位コードかどうか
Function IsHighSurrogate(ByVal code As Integer) As Boolean
    
    If (&HD800 <= code And code <= &HDBFF) Then
        ' 上位
        IsHighSurrogate = True
    Else
        ' それ以外
        IsHighSurrogate = False
    End If
    
End Function
  
' 指定した文字コードがサロゲートの下位コードかどうか
Function IsLowSurrogate(ByVal code As Integer) As Boolean

    If (&HDC00 <= code And code <= &HDFFF) Then
        ' 下位
        IsLowSurrogate = True
    Else
        ' それ以外
        IsLowSurrogate = False
    End If
    
End Function

IsReverseSurrogate 関数に「StrReverse 関数」で反転されている文字列を渡して、その最初の文字がサロゲートペア文字か判定します。True ならサロゲートペア文字です。


' 指定した反転された文字列の最初の文字がサロゲートペア文字かどうか
Function IsReverseSurrogate(ByVal text As String) As Boolean
    ' 1 文字はサロゲートペアではない
    If Len(text) <= 1 Then
        IsReverseSurrogate = False
        Exit Function
    End If
    
    ' 下位を取得
    Dim low As Integer
    low = AscW(Mid(text, 1, 1))
    
    Dim isLow As Boolean
    isLow = IsLowSurrogate(low)
    
    ' 上位を取得
    Dim high As Integer
    high = AscW(Mid(text, 2, 1))
    
    Dim isHigh As Boolean
    isHigh = IsHighSurrogate(high)
    
    ' サロゲートペア
    IsReverseSurrogate = (isLow And isHigh)
End Function

列挙する

Unicode 文字やサロゲートペア文字が含まれた文字列を列挙するには次のようにします。サロゲートペア文字が 2 文字分あることに注意すれば、通常の文字列と変わりません。上記で作成した判定用の関数を使用しています。


Dim s As String ' 列挙する文字列
s = "あ" & WorksheetFunction.Unichar(38960) & WorksheetFunction.Unichar(171581) ' あ𩸽😃

Dim length As Integer
length = Len(s) ' 4、列挙する文字数

Dim char As String  ' 列挙された 1 文字
Dim high As Integer ' その上位コード

' 列挙する
Dim i As Integer
For i = 1 To length

    char = Mid(s, i, 1) ' 1 文字取得
    high = AscW(char)
    
    If IsSurrogate(Mid(s, i)) Then
        ' サロゲートペア文字
        char = Mid(s, i, 2) ' 2 文字取得
        i = i + 1
        
    ElseIf IsHighSurrogate(high) Then
        ' 上位だけで下位がない異常な文字

    ElseIf IsLowSurrogate(high) Then
        ' 下位だけで上位がない異常な文字

    Else
        ' Unicode を含む文字

    End If
    
    Range("A" & i).Value = char
Next

ファイルの読み書き

Unicode を読み込めるかどうかは使用するオブジェクトに依存します。

表示する

Shift_JIS に存在しない Unicode 文字を Debug.Print や MsgBox で表示すると?に変換されます。

試していませんが、Windows 10 の [設定] - [時刻と言語] - [言語] - [管理用の言語設定] - [システムロケールの変更] - [ワールドワイド言語サポートでの Unicode UTF-8 を使用] をチェックすると表示できるかもしれません。

ただし、すべてアプリに対して影響があるので、Unicode に対応していないアプリで問題が発生する可能性があります。

  • 目次
    • VBA の Unicode 対応状況
    • 変換する
    • 入力する
    • 判定する
    • 列挙する
    • ファイルの読み書き
    • 表示する