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

ExcelマクロVBAの問題点と解決策、VBAの技術的解説
公開日:2019-08-20 最終更新日: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文字コードか判定する
・文字コードについて ・UnicodeにあってShift_JISにない文字の具体例 ・シート構成 ・配列数式での判定 ・Shift_JIS文字コードか判定するマクロVBA全コード ・最後に

UTF-8
BOM付きとBOM無しがあります。
BOM無しはUTF-8Nと言われたりします。
VBAでWEB関係のCSVを扱う時に必要となりますが、VBAでUTF-8を扱う場合はADODB.Streamを使います。
CSVの読み込み方法(改の改)
・CSVの形式について ・CSV読み込みVBAコード ・配列を使ってシートにまとめて出力する場合 ・QueryTablesを使ったCSV読み込み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関数 ・Len関数の注意点 ・Len関数の使用例

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技術解説」の記事

Excelアドインの作成と登録について

・Excelアドインについて ・アドインファイルのフォルダ ・アドインの作り方 ・アドインの登録と有効化 ・ ・アドインで保存するVBA ・アドインを登録するVBA ・アドインを有効化するVBA ・登録されているアドインを確認するVBA ・アドインマネージャーを表示するVBA ・アドイン配布時に自動登録するVBA ・個人用マクロブックについて
VBAでのタイマー処理(SetTimer,OnTime)
・Application.OnTime メソッド ・WindowsAPI:SetTimer関数 ・最後に
マクロでShift_JIS文字コードか判定する
・文字コードについて ・UnicodeにあってShift_JISにない文字の具体例 ・シート構成 ・配列数式での判定 ・Shift_JIS文字コードか判定するマクロVBA全コード ・最後に
Byte配列と文字コード関数について
Applicationを省略できるApplicationのメソッド・プロパティ一覧
・Applicationを省略できるかどうかの確認 ・Applicationを省略できるApplicationのメソッド一覧 ・Applicationを省略できるApplicationのプロパティ一覧 ・最後に一言
PowerQueryの強力な機能をVBAから利用する方法
・説明に使用するデータ ・PowerQueryの操作方法 ・PowerQueryのマクロの記録 ・PowerQueryのVBA文法 ・PowerQueryの機能を利用したマクロVBA ・PowerQueryについて
ShapesとDrawingObjectsの相違点と使い方
・Shapes コレクション ・DrawingObjects コレクション ・ShapesとDrawingObjectsの相違点 ・DrawingObjectsの便利な使い道 ・最後に ・図形オートシェイプ(Shape)に関連する記事
新規挿入可能なシート名の判定
・シート名として使える文字列か判定 ・シートの存在確認:存在すればシートのオブジェクトを返す ・シートの挿入:存在すればシートのオブジェクトを返す
VBAにおける配列やコレクションの起点について
・配列の起点について ・コレクション ・Collectionオブジェクト ・その他:文字列関数 ・配列の起点の原則
VBAのマルチステートメント(複数のステートメントを同じ行に)
・VBAでのステートメントという用語について ・行継続(1ステートメントを複数の行に) ・VBAマルチステートメントの基本 ・VBAマルチステートメントの応用 ・マルチステートメントの最後に
クリップボードに2次元配列を作成してシートに貼り付ける
・クリップボードのデータ取得/クリップボードへデータ送信 ・エクセルの行・列のデータ ・クリップボードに2次元配列を作成してシートに貼り付けるVBA ・クリップボードに2次元配列の最後に


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

ExcelマクロVBA入門目次|エクセルの神髄(2024-03-20)
VBA10大躓きポイント(初心者が躓きやすいポイント)|VBA技術解説(2024-03-05)
テンキーのスクリーンキーボード作成|ユーザーフォーム入門(2024-02-26)
無効な前方参照か、コンパイルされていない種類への参照です。|エクセル雑感(2024-02-17)
初級脱出10問パック|VBA練習問題(2024-01-24)
累計を求める数式あれこれ|エクセル関数応用(2024-01-22)
複数の文字列を検索して置換するSUBSTITUTE|エクセル入門(2024-01-03)
いくつかの数式の計算中にリソース不足になりました。|エクセル雑感(2023-12-28)
VBAでクリップボードへ文字列を送信・取得する3つの方法|VBA技術解説(2023-12-07)
難しい数式とは何か?|エクセル雑感(2023-12-07)


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

1.最終行の取得(End,Rows.Count)|VBA入門
2.RangeとCellsの使い方|VBA入門
3.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
4.繰り返し処理(For Next)|VBA入門
5.変数宣言のDimとデータ型|VBA入門
6.ブックを閉じる・保存(Close,Save,SaveAs)|VBA入門
7.並べ替え(Sort)|VBA入門
8.条件分岐(IF)|VBA入門
9.セルのクリア(Clear,ClearContents)|VBA入門
10.マクロとは?VBAとは?VBAでできること|VBA入門




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


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



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