-
∨目次
- VBA の Unicode 対応状況
- 変換する
- 入力する
- 判定する
- 列挙する
- ファイルの読み書き
- 表示する
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 文字は直接入力や表示はできません。?になります。
サロゲートペア文字は上位と下位の 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) ' 😃
「エクセル 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) ' 𩸽
判定する
サロゲートペア文字か判定するための関数を作成します。
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 を読み込めるかどうかは使用するオブジェクトに依存します。
- 「Input 関数」:Shift-JIS のみ読み込めます。
- 「FileSystemObject」:Shift-JIS と UTF-16 を読み込めます。
- 「QueryTables」:Shift-JIS と UTF-8 を読み込めます。UTF-16 も良ければ読み込めます。
- 「Workbooks」:Shift-JIS と UTF-8 を読み込めます。UTF-16 も良ければ読み込めます。
表示する
Shift_JIS に存在しない Unicode 文字を Debug.Print や MsgBox で表示すると?に変換されます。
試していませんが、Windows 10 の [設定] - [時刻と言語] - [言語] - [管理用の言語設定] - [システムロケールの変更] - [ワールドワイド言語サポートでの Unicode UTF-8 を使用] をチェックすると表示できるかもしれません。
ただし、すべてアプリに対して影響があるので、Unicode に対応していないアプリで問題が発生する可能性があります。
スポンサーリンク