ExcelマクロVBA技術解説
Byte配列と文字コード関数について

ExcelマクロVBAの問題点と解決策、エクセルVBAの技術的解説
最終更新日:2019-09-19

Byte配列と文字コード関数について


マクロVBAのデータ型にByte型がありますが、使う機会はかなり限られています。
バイト型は、8 ビット (1 バイト) の変数で、0~255の範囲の単精度の正の数値が格納されます。


1バイトで使う事もなくはありませんが、Byte型配列として使われることがしばしばあります。
今回はByte配列に文字列を入れることで、文字コードについて考察してみます。

今回の記事は、実用としては何も役に立つものはありません。
文字コードとは面倒なものだなーと、それくらいの意識で読んでもらえれば良いと思います。

以下では、半角全角ひらがな漢字を入れ込んだ「Excelの神髄」を例にしています。

文字列をByte配列に入れる

文字列(String)は直接Byte配列に入れることができます。



Sub 文字列_Byte配列()
  Dim aryByte() As Byte
  aryByte = "Excelの神髄"
  Stop
End Sub

バイト配列の宣言は、
Dim aryByte() As Byte
普通にByteを配列として宣言します。
配列の要素数は文字数に依存するので、今回は動的配列にしています。
このByte配列には、文字列(String)を直接代入できます。

Stopの時点で、ローカルウインドウを見てみましょう。

VBA マクロ Byte配列 文字コード

バイト型なので、0~255の数値が入っているのが分かります。
この数値が文字コードになります。
ですが、文字コードは色々な種類があると聞いたことがある・・・
では、文字コードについて少し確認してみましょう。

文字コードについて

まず基本として、
ASCIIコードは、数字、アルファベット、記号を1バイトで表現
JISコードは、ASCIIコードに日本語(全角)を追加した文字コード
Shift_JISは、半角はJISコードのまま、全角文字をJISコードからシフトした文字コード
Unicodeは、符号化文字集合で、文字コードの国際的な業界標準
UTF-8,UTF-16は、Unicodeを実装した符号化方式です。

VBAで問題となる部分をもう少し詳しく見て見ましょう。

Shit-JIS
Windowsでは標準ともいえる文字コードです。
Windowsで作成したcsvなら、ほとんどがShit-JISでしよう。
メモ帳で保存時には、「ANSI」になります。

VBEでは、Shift-JISが使われています。
マクロでShift_JIS文字コードか判定する
環境依存文字・機種依存文字をチェックしたいという話は時々聞くことなのですが何をもってして判別するかという事が実はとても難しい問題になります①②もIMEでは[環境依存]と表示されますが通常これが問題になる事はないでしょう。そもそもコンピューターの中は2進数だけで表現されているものでコンピューターの文字とは

UTF-8
BOM付きとBOM無しがあります。
BOM無しはUTF-8Nと言われたりします。
VBAでWEB関係のCSVを扱う時に必要となりますが、VBAでUTF-8を扱う場合はADODB.Streamを使います。
CSVの読み込み方法(改の改)
CSVのVBAでの読込方法については複数の記事を掲載しており、人気記事として多くのアクセスがあります。掲載しているVBAコードは汎用的に書いてあり、ほぼそのまま使用できるものです。しかし、CSVは多くの形式(区切り文字、文字コード等)があり、今まで掲載したコードでは解決出来ないものがあります。

UTF-16
Unicodeには、複数バイトで構成されるデータの並べ方で、エンディアンというものがあり、
ビッグエンディアンとリトルエンディアンがあります。
メモ帳でも保存時の、
「Unicode」は、UTF-16のリトルエンディアン
「Unicode big endian」は、UTF-16のビッグエンディアン

文字コード、例えば「あ」をUTF-16の16進法で表現したとき、
上位側から順に並べ「30 42」とするのがビッグエンディアン、
下位側から「42 30」のように並べるのをリトルエンディアンと呼びます。
UTF-16のビッグエンディアンを、UTF-16BE
UTF-16のリトルエンディアンを、UTF-16LE
このように表記されたりします。
エンディアンの詳細について知りたい場合は別途検索してください、詳しく説明しているページが多数存在します。

VBAでは、UTF-16LEが使われています。
つまり、先に掲載したローカルウインドウのaryByteの中身は、UTF-16LEだという事です。
ローカルウインドウでは、この文字コードが10進で表示されています。

以下では、
VBEで使われているShift-JISとVBAで使われているUTF-16LEについて、
マクロVBAでByte配列と関数を使って少し詳しく見ていきます。

文字列をByte配列に入れて、文字列に戻す

文字列(String)をByte配列に入れた後で、再度文字列に戻します。

Sub 文字列_Byte配列_文字列()
  Dim aryByte() As Byte
  aryByte = "Excelの神髄"
  
  Dim str As String
  str = aryByte
  Debug.Print str
End Sub

このように、Byte配列は単純に文字列(String)に入れることができます。
VBAでは、暗黙の型変換が行われるので、
Debug.Print aryByte
これだけでも正しく元の文字列が表示されます。

文字列をByte配列に入れて、自力で文字列に戻す

上記では、VBAが自動でByte配列に入っている文字列(String)を元の文字列に戻してくれましたが、
何をしているのか、なんだかよく分かりません。
そこで、自力でByte配列を文字列に戻してみましょう。



Sub 文字列_Byte配列_自力文字列()
  Dim aryByte() As Byte
  aryByte = "Excelの神髄"
  
  Dim str As String: str = ""
  Dim i As Long
  For i = 0 To UBound(aryByte) - 1 Step 2
    str = str & ChrW(aryByte(i + 1) * 256& + aryByte(i))
  Next
  Debug.Print str
End Sub

VBAでは、UTF-16LEが使われています。
つまり、aryByteの中の順番は、
2バイト(1文字)ごとに、順番が入れ替わっています。
aryByte(0) aryByte(1)
これは、aryByte(1) aryByte(0)の順として文字コードを見る必要があります。
1バイトの数値は256なので、2バイトで1つの数値とするには、
aryByte(i + 1) * 256& + aryByte(i)
これで、2バイトの文字コードを10進に変換できることになります。
256&の&はLong型の型宣言文字になります。
この&がないと、オーバーフローが発生します。

VBA マクロ Byte配列 文字コード

これは、
aryByteも256も、どちらもInteger型なので、掛け算の結果もInteger型になってしまう為に発生します。
いずれかがLong型であれば結果もLongになるので、256&としています。

Chr関数とChrW関数
Chr関数は、指定したShif-JIS文字コードに対応する文字を返します。
ChrW関数は、指定したUTF-16文字コードに対応する文字を返します。

文字列をSJISに変換してからByte配列にいれて、自力で文字列に戻す

マクロVBAで、サーバーにPOSTしてデータ取得するようなときには、パラメーターをShift-JISのBYTE型に変換します。
Shift-JISのBYTE型に変換するには、StrConvのvbFromUnicodeを使います。

では、イミディエイトウインドウで、
?StrConv("Excelの神髄", vbFromUnicode)
といれてEnterしてみると、

VBA マクロ Byte配列 文字コード

何やら文字化けしています。
Shift-JISなら正しく表示されそうですが、、、
VBEはShift-JISですが、VBAはUTF-16LEです。
つまり、StrConvでShift-JISになっているものを、UTF-16LEとして判断されている為に文字化けしています。

では、
StrConvでShift-JISになっているものを、UTF-16LEに戻してみましょう。

Sub 文字列_SJIS_Byte配列_自力文字列()
  Dim aryByte() As Byte
  aryByte = StrConv("Excelの神髄", vbFromUnicode)
  
  Stop '←ここでローカルウインドウで確認
  
  Dim str As String: str = ""
  Dim i As Long: i = 0
  Do
    If (aryByte(i) >= 128 And aryByte(i) <= 159) Or _
      (aryByte(i) >= 224 And aryByte(i) <= 255) Then
      str = str & Chr(aryByte(i) * 256& + aryByte(i + 1))
      i = i + 2
    Else
      str = str & Chr(aryByte(i))
      i = i + 1
    End If
    If i > UBound(aryByte) Then Exit Do
  Loop
  Debug.Print str
End Sub

Stop時点でローカルウインドウでみてみると、

VBA マクロ Byte配列 文字コード

単に、
aryByte = "Excelの神髄"
とした時とは、配列の要素数が違うようです。
UTF-16LEでは、全て2バイトでしたが、
Shift-JISでは、半角は1バイト、全角は2バイトとなっています。
つまり、
(0)~(4)は半角文字で1バイトで1文字、
(5)~(10)は全角文字で2バイトで1文字ということです。
Shift-JISの半角が1バイトであることは、
VBAにおいて、文字列中の半角文字数の判定に使う事が出来ます。
Len関数,LenB関数
Len関数は、指定した文字列の文字数を、LenB関数はバイト数を返します、長整数型(Long)の値を返します。Len関数 Len(string|varname) string 任意の文字列式を指定します。引数stringにNull値が含まれている場合は、Null値を返します。

Shift-JISの文字コードは、半角文字(1バイト)は以下のように割り当てられています。

下位4ビット
0 1 2 3 4 5 6 7 8 9 A B C D E F


4


0 NUL SOH STX ETX EOT ENQ ACK BEL BS HT LF VT FF CR SO SI
1 DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US
2 SP ! " # $ % & ' ( ) * + , - . /
3 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
4 @ A B C D E F G H I J K L M N O
5 P Q R S T U V W X Y Z [ \ ] ^ _
6 ` a b c d e f g h i j k l m n o
7 p q r s t u v w x y z { | } ~ DEL
8                                
9                                
A
B ソ
C
D
E                                
F
※文字コードの詳しい表はWEBに多数ありますので別途調べてください。

Shift-JISの全角文字は2バイトで、最初の1バイトが上記表の黄色部分が使われています。
つまり、最初の1バイトが上表の黄色部分なら全角文字だという事になります。
10進で表現した時は、128~159,224~255の範囲という事です。
この範囲の時は、次の1バイトと合わせて2バイトで全角1文字になるという事です。

最後に

マクロVBAで文字コードを意識することは滅多にないでしょう。
ましてや、Windowsを使っているとUnicodeを意識することはほとんどないでしょう。
私も普段はほとんど意識することはありません。
従って、本記事もいろいろ確認しながら書いたものになります。

文字コードが多種多様なことは、コンピューターの歴史そのものでもありますが、
現在においては負の遺産と言っても良いかもしれません。
いずれ全く意識する必要がなくなる日が来るとは思います。
しかし現在はまだまだこれを考慮しなければならない場面も出てきますので、
IT知識の一端として紹介したものになります。



同じテーマ「マクロVBA技術解説」の記事

オブジェクト式について
オブジェクトの探索方法
条件付きコンパイル(32ビット64ビットの互換性)
ドキュメントプロパティ(BuiltinDocumentProperties,CustomDocumentProperties)
VBAでファイルを規定のアプリで開く方法
Excelアドインの作成と登録について
VBAでのタイマー処理(SetTimer,OnTime)
マクロでShift_JIS文字コードか判定する
Byte配列と文字コード関数について
VBA+SeleniumBasicで検索順位チェッカー(改)
Applicationを省略できるApplicationのメソッド・プロパティ一覧


新着記事NEW ・・・新着記事一覧を見る

文字列結合&でコンパイルエラーになる理由|VBA技術解説(9月19日)
Byte配列と文字コード関数について|VBA技術解説(8月20日)
PowerQueryの強力な機能をVBAから利用する方法|VBA技術解説(8月4日)
練習問題31(セル結合を解除して値を埋める)|VBA練習問題(7月30日)
練習問題30(マトリックス→リスト形式)|VBA練習問題(7月25日)
Applicationを省略できるApplicationのメソッド・プロパティ一覧|VBA技術解説(7月22日)
コレクション(Collection)の並べ替え(Sort)に対応するクラス|VBA技術解説(7月20日)
CSVの読み込み方法(ジャグ配列)|VBAサンプル集(7月15日)
その他のExcel機能(グループ化、重複の削除、オートフィル等)|VBA入門(7月14日)
オートフィルタ退避回復クラスを複数シート対応させるVBAクラス|VBA技術解説(7月6日)


アクセスランキング ・・・ ランキング一覧を見る

1.最終行の取得(End,Rows.Count)|VBA入門
2.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
3.RangeとCellsの使い方|ExcelマクロVBA入門
4.Range以外の指定方法(Cells,Rows,Columns)|VBA入門
5.変数とデータ型(Dim)|ExcelマクロVBA入門
6.繰り返し処理(For Next)|ExcelマクロVBA入門
7.マクロって何?VBAって何?|ExcelマクロVBA入門
8.セルに文字を入れるとは(Range,Value)|VBA入門
9.ひらがな⇔カタカナの変換|エクセル基本操作
10.空白セルを正しく判定する方法(IsEmpty,IsError,HasFormula)|VBA技術解説



  • >
  • >
  • >
  • Byte配列と文字コード関数について

  • このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。


    記述には細心の注意をしたつもりですが、
    間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
    なお、掲載のVBAコードは自己責任で使ってください。万一データ破損等の損害が発生しても責任は負いません。




    このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
    本文下部へ