【発掘】 [ACC2000] Unicode(UTF-16(LE)) と文字列操作関数の留意点Len,Asc,Chr,Mid

# VBAとAccessの文字列操作関数の違い
まず、ExcelなどのVBAについて確認する。
Macでは使えないものもあるが、本稿ではそこは取り上げない。
なお、Excelのワークシート関数のLenBも挙動が違うことがあるので注意すること。(補足参照）
## Excel （VBA）などのふつうのVBA関数
### Input関数
[Input 関数](https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/input-function)
ここにInputBがある
#### ステートメントとの区別
なお、[Input # ステートメント](https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/inputstatement)と混同しないように注意すること。
#### InputとInputBの挙動の違い。
[InputB - OfficeTanaka](officetanaka.net/excel/vba/function/InputB.htm)
バイナリの場合、行という概念がなくなる。なので固定長のデータベースがよいことになる。
[テキストファイル：データを読み込む（Input 関数・InputB 関数） ](https://excelwork.info/excel/inputfunction/)
この時バイナリではEOFを使用しないことに注意する必要がある。
### そのほかの関数
[Len関数](https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/len-function)
実はLenBの説明がある
[Mid 関数](https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/mid-function)
実はMidBの説明がある。
[Left 関数](https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/left-function)
[Right 関数](https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/right-function?source=recommendations)
[変換関数 Asc(Asc,AscB, AscW)](https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/asc-function)
<BlockQuote>
文字列の最初の文字に対応した文字コードを示す整数を返します。

##### 構文
Asc(string)
必要な 文字列引数 は、任意の有効な 文字列式です。 string に文字が含まれていない場合、実行時エラーが発生します

##### 注釈
戻り値の範囲は、DBCS 以外のシステムでは 0 から 255 ですが、 DBCS システムでは -32768 から 32767 です。

::: note warn
<b>AscB</b> 関数は、文字列に含まれるバイト データの場合に使用します。 先頭の文字の文字コードを返す代わりに、<b>AscB</b> は最初のバイトを返します。 <b>AscW</b> 関数は、Unicode 文字コードを返します。ただし、Unicode がサポートされていないプラットフォームでは、<b>Asc</b> 関数と同じ動作になります。
:::
::: note warn
Visual Basic for the Macintosh では、Unicode 文字列をサポートしていません。 したがって、 <b>AscW (n)</b> は、Windows 環境と同様に、128 から 65,535 の範囲の n 個の値のすべての Unicode 文字を返すことはできません。 代わりに、<b>AscW (n)</b> は、127 より大きい Unicode 値 n について "最適なものを推測" します。 したがって、Macintosh 環境では、<b>AscW</b> を使用してはいけません。。
:::

</BlockQuote>

[変換関数 Chr(Chr, ChrB, ChrW)](https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/chr-function)

[StrComp 関数](https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/strcomp-function)
Opiton Compare Textで挙動が変わる。何も書かないとBinary。ただし、AccessはOption Compare Databaseの時があるので冒頭に注意。ここだけでも挙動が変わる。

[StrConv 関数](https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/strconv-function)
vbFromUnicodeを使用するとANSIのBinary配列になる。VBAの内部ではUTF-16LEの配列になっている。

[String関数](https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/string-function)
String関数で使える文字はコード番号256まで。

[文字列操作キーワードの概要](https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/string-manipulation-keyword-summary)
上記の記事では、これらの関数の一覧はキーワードとして表がある。なぜキーワード？
[関数から文字列を返す](https://learn.microsoft.com/ja-jp/office/vba/language/concepts/getting-started/returning-strings-from-functions)
上記の記事では、Midなどの関数の返り値はVariant型の時もあるので、`$`をつけて文字列型にすることができる関数があることを説明している。
[入力関数と InputB 関数 (文字列関数操作の違い)](https://learn.microsoft.com/ja-jp/office/vba/access/concepts/miscellaneous/input-and-inputb-functions-differences-in-string-function-operations)

[InputB関数](https://www.mermaid-tavern.com/taro/ipc/ip2/ipc_0052.html)
<OL>
<li>読み込む対象ファイルがUnicode(補足：UTF-16(LE))の場合、Input関数もInputB関数も実行結果はほぼ同じである。
<li>読み込む対象ファイルがShift_JISの場合、Input関数とInputB関数の実行結果は大いに異なる。 
</OL>
口は悪いが、
VBAのInput関数はShift-Jisの場合は<b>Shift-Jisの文字列</b>として読み込んでいる。
VBAのInputB関数とはUTF-16LEを前提として読み書きする関数だったということである。

# Accessの場合
## [入力関数と InputB 関数 (文字列関数操作の違い)](https://learn.microsoft.com/ja-jp/office/vba/access/concepts/miscellaneous/input-and-inputb-functions-differences-in-string-function-operations)
<blockquote>
2023/02/18
適用先: Access 2013 | Access 2016

テキストのメモリストレージ形式は、Visual Basic for Applications (VBA) コードと Access Basicコードによって異なります。 (Access Basic は、以前のバージョンの Microsoft Access で使用されていました)。テキストは、Access Basic コード内の ANSI 形式と Visual Basic の Unicode 形式で格納されます。 このトピックでは、現在のバージョンの Microsoft Access で文字列を処理するときの潜在的な問題の 1 つについて説明します。

詳細については、「 文字列関数操作の相違点」を参照してください。
Microsoft Access の Input 関数は、文字をファイルから読み出すときに指定した文字数を Unicode の文字列に変換して変数に読み込みます。 一方、InputB 関数は、データをバイナリ データであると仮定して Unicode には変換せずにそのまま変数に格納します。 次のように固定長のフィールドで格納されているファイルを読むときに InputB 関数を使う場合は、固定バイト長のデータを読み込んでから Unicode に変換する必要があります。

```VB
Open "Data.Dat" For Input As 1 
dat1 = StrConv(InputB(10, 1), vbUnicode) 
dat2 = StrConv(InputB(10, 1), vbUnicode) 
dat3 = StrConv(InputB(10, 1), vbUnicode) 

===DATA.DAT 
123456789012345678901234567 
Name Address Telephone
```
</blockquote>
これはInput関数はShift-JisであろうとUTF-16LEであろうとUTF-16LEに変換されていることを意味している。
他方InputBはShift-JisだろうとUTF-16LEだろうとすべてそのまま読み込む。このままではUTF-16LEの文字列にはならないのでStrConvが必要となる。という意味になる。
しかし文字列関数操作の相違点は英語であり、今の概念の項目とはすべて対応していない。

[Differences in String Function Operations](https://learn.microsoft.com/en-us/previous-versions/office/developer/office-2010/ff192883(v=office.14)?redirectedfrom=MSDN)
ここからさらに次の記事がリンクされている。

 +　[Asc Function and AscB Function](https://msdn.microsoft.com/en-us/library/ff836919(v=office.14))　※[Asc関数](https://support.microsoft.com/ja-jp/office/asc-%E9%96%A2%E6%95%B0-ad4b9d2d-446a-4d96-9cc7-e1afeb3d6dc3)にはこのような詳細な記述はない
 +　[Chr Function and ChrB Function](https://msdn.microsoft.com/en-us/library/ff822423(v=office.14)) ※[Chr関数](https://support.microsoft.com/ja-jp/office/chr-%E9%96%A2%E6%95%B0-94e7d144-8ba7-4082-8519-e5dd1b451b85)もAsc関数と同じ
 +　[Calling the Windows API](https://learn.microsoft.com/en-us/previous-versions/office/ff836378(v=office.14)?redirectedfrom=MSDN) ※[Windows API の呼び出し (文字列関数操作の違い)](https://learn.microsoft.com/ja-jp/office/vba/access/concepts/miscellaneous/calling-the-windows-api-differences-in-string-function-operations)に相当
 +　[Input and InputB Functions](https://msdn.microsoft.com/en-us/library/ff193456(v=office.14))※これは日本語の記事に相当、ほかAccess用のSupport版の[Input関数](https://support.microsoft.com/ja-jp/office/input-%E9%96%A2%E6%95%B0-5a666c45-6048-405f-bdfe-c5209c45756d)もある
 +　[Processing ANSI String Bytes](https://msdn.microsoft.com/en-us/library/ff821480(v=office.14))
 +　[Sample Functions that perform operations that are compatible with byte processing functions of 16-bit versions](https://msdn.microsoft.com/en-us/library/ff820954(v=office.14))
 +　[Using the Byte Data Type](https://msdn.microsoft.com/en-us/library/ff197051(v=office.14))

また、これらの記事のサンプル、記述はバグっているときがある。
[Asc Function and AscB Function (Differences in String Function Operations)](https://learn.microsoft.com/en-us/previous-versions/office/ff836919(v=office.14)?redirectedfrom=MSDN)
> テキストのメモリ ストレージ形式は、Visual Basic for Applications (VBA) コードと Access Basic コードで異なります。 (Access Basic は、Microsoft Access の初期のバージョンで使用されていました。) テキストは、Access Basic コード内では ANSI 形式で格納され、Visual Basic では Unicode 形式で格納されます。このトピックでは、現在のバージョンの Microsoft Access で文字列を処理する際に発生する可能性がある問題について説明します。詳細については、文字列関数の操作の違いを参照してください。

このプログラムは以前のバージョンの Access では正しく実行されましたが、現在のバージョンの Microsoft Access の Visual Basic では実行時エラーが発生します。
```vb
Print Asc(MidB("Invalid DDUE based on source, error:image not allowed in code, image filename:40b8bf3c-83b2-8930-567d-3d0ebedd3b61", 2,1))
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126919/f94f1c6a-a610-17b1-45d3-a4277aa56362.png)

さらにUsing Byte Data Typeでは
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126919/fcca5ae8-e77b-4391-5d15-8108f169840e.png)

とコードはおろか記述も日本語と混じっている。ブラウザのせいなのか。。。




#  [ACC2000] Unicode と文字列操作関数の留意点
元のURL:`http://support.microsoft.com/kb/404928/ja`
StrConv 関数 - Access - Microsoft Office Online
元のURL:http://office.microsoft.com/ja-jp/access/HA012289151041.aspx
## 発掘すべき理由
上記の英語で記載されている大部分の内容は以下の2つの資料でおおむね判明する。しかもバラバラになっているのに対し、統合されている。
さらに経緯も若干詳しい。

- [ACC2000] Unicode と文字列操作関数の留意点
- INFO: Asc/AscB/AscW と Chr/ChrB/ChrW の間の関数の違い

Infoについては日本語になっていないので、再度翻訳した。

## 概要
この資料は、以前のバージョンの Access Basic の関数と異なる結果を返す Microsoft Visual Basic Programming System Applications (以下 VBA) の文字列操作関数につい て説明しています。

## 詳細
Access 95 以降では Unicode が採用されました。それに伴い VBA の文字列を操作する関 数が、Access 1.1 や Access 2.0 の Access Basic の関数と異なる結果を返す場合があ ります。ここでは、Access 95 以降で文字列を操作する関数を使う上での留意点につい て説明します。
### Unicode とは
Unicode は、ANSI および拡張 ASCII 文字標準の 256 文字を超える文字数をサポートす ることを目的として、国際標準化機構 (ISO) が開発した文字標準です。ANSI および 拡 張 ASCII 標準は、共に 8 ビット (1 バイト) 文字コードを使用しており、これが重複 しない文字数を 256 文字に制限しています。
これに対して Unicode は、16 ビット (2 バイト) コード スキーマを使用するため、 65,536 の個別文字空間を実現し、現在は、約 34,000 文字が割り当てられています。こ れは、現在、世界中で使用されているすべての文字およびアルファベットに適応し、サ ンスクリットおよびエジプト象形文字など、各種の古代言語も含まれます。Unicode に は区切り記号、数学記号などが含まれています。
### Access Basic と VBA の文字の格納形式の違い
VBA での文字列のメモリ上での格納形式は、Access 1.1 や Access 2.0 の Access Basic と異なっています。Access Basic では ANSI 形式で格納されていましたが、Access 95 以降では Unicode 形式で格納されます。
これは、VBA が密接な関係をもっている、OLE 内部での文字列形式にあわせるためです。 例えば、"ABC あいう" という文字列は、ANSI 形式と Unicode 形式で次のようにメモリ 上に格納されます。表内の数値は、16 進数で表記しています。
```text
    格納形式 : Unicode
    格納状態 :

    41 00 42 00 43 00 42 30 44 30 46 30 
    ----- ----- ----- ----- ----- -----   
     A     B     C     あ    い   う

    説明 : 各文字が 2 バイトで格納されます。
```
```text
    格納形式 : ANSI
    格納状態 :

    41 42 43 82 A0 82 A2 82 A4 
    -- -- -- ----- ----- ----- 
     A  B  C    あ    い    う

    説明 : 日本語文字は 1 文字が 2 バイトで格納されます。
```
この内部形式の違いによって、VBA と Access Basic では、結果の異なることがある関 数やステートメントがあります。Access Basic で、文字列のバイト数や、文字コードそ のものに依存するコードを記述している場合は注意が必要です。
例えば、LenB("A") の結果は、Access Basic では 1 ですが、VBA では 2 になります。
### VBA と Access Basic で結果の異なる可能性のある関数、ステートメント
VBA と Access Basic で結果の異なる可能性のある関数、ステートメントには、次のものがあります。
```text
    Asc 関数
    Chr 関数
    InputB 関数
    InstrB 関数
    LeftB 関数
    LenB 関数
    RightB 関数
    MidB 関数
    および、これら関数に対等するステートメント
```
VBA では、その他に AscB 関数、AscW 関数、ChrB 関数、ChrW 関数がサポートされてい ます。以下に、VBA でのコーディングをする上で留意する必要のある点を記述します。
### VBA で、ANSI文字列の操作をおこなう場合
VBA で ANSI 文字列の操作をおこなう場合には、StrConv 関数を使用して、Unicode 形 式 と ANSI 形式間の文字列変換処理をおこなう必要があります。StrConv 関数は、引数 vbFromUnicode を指定して、Unicode 文字列から ANSI 文字列への変換、また、引数 vbUnicode を指定して、ANSI 文字列から Unicode 文字列への変換ができます。
ANSI 文字列の操作をおこなうプログラムは次のようなフローになります。
```vb
    Dim s as String
  ' ANSI 形式へ変換します。
    s=StrConv("ABC あいう", vbFromUnicode)
  '
  ' ここで、
  ' ANSI 文字列に対してのバイト単位の操作をおこないます。
  ' ただし、一般の文字単位の操作はできません。
  '
  ' Unicode 形式へ戻します。
    s=StrConv(s, vbUnicode)
```
### 文字のバイト数を利用したプログラム
Access Basic では、ASCII 文字のように 1 バイトで表される文字と、漢字のように 2 バイトで表される文字があります。VBA では、すべての文字は 2 バイトの Unicode で 表されます。例えば、"A" という文字のバイト数は、Access Basic では 1 ですが、VBA では 2 になります。
Access Basic で記述された、文字のバイト数に依存したプログラムは、VBA に合わせて 修正が必要な場合があります。文字列の文字数を取得する関数には、Len 関数がありま す。また、バイト数を取得する関数には、LenB 関数があります。

  文字列内の文字数の取得             Len 関数
  文字列のバイト数の取得             LenB 関数

Access Basic では、ある文字が漢字かどうかを、文字数とバイト数の関係から判断する ことができました。漢字では、バイト数が、文字数の 2 倍になります。しかし、VBA で 採用している Unicode では、すべての文字で、この関係が成り立ちます。VBA で Access Basic と同じロジックでプログラムを作成するには、バイト数を求める前に、Unicode 文 字を ANSI 文字に変換する必要があります。
以下に、ANSI 文字列のバイト数を利用したプロシージャを紹介します。

例）文字列の種類を求める
次の IsKanji プロシージャでは、引数の文字列の種類を判断します。2 バイト文字 だけの場合は -1 を、1 バイト文字だけの場合は 1 を、混在している場合には 0 を返します。
```vb
Function IsKanji(strUnicode As String)
    Dim strANSI As String
    Dim lchar As Integer, lbyte As Integer
    strANSI = StrConv(strUnicode, vbFromUnicode)
    lchar = Len(strUnicode)
    lbyte = LenB(strANSI)
    If lchar * 2 = lbyte Then
        IsKanji = -1
    ElseIf lchar = lbyte Then
        IsKanji = 1
    Else
        IsKanji = 0
    End If
  End Function
```
### 文字コードを利用したプログラム
VBA では、システムの既定のコード ページ内の文字コードと Unicode を対象とする関 数があります。そのため、どちらの文字コードで処理するのかを意識してコーディング する必要があります。文字と文字コードの変換関数として、Asc 関数と Chr 関数があ ります。VBA では、その他に AscB 関数と AscW 関数、ChrB 関数が用意されています。
文字から文字コードを取得する
システムの既定のコード ページ内の文字コードを取得するには、Asc 関数を使用しま す。また、Unicode を取得するには、AscW 関数を使用します。どちらのコードが必要 なのかによって、使い分ける必要があります。

 システムの既定のコード ページ内の文字コードの取得               Asc 関数
 Unicode の取得                                                  AscW 関数

VBA の Asc 関数は、引数として Unicode 文字列をとります。1 バイト文字の文字コー ドを取得するには、AscB 関数を使用しなければいけません。例えば、"あ"という文字 の文字コードの 2 バイト目を表示するような、バイト単位で操作するプログラムでは 注意が必要です。
Access Basic では、1. のように記述します。VBA では、1. の記述ではエラーが発生 します。MidB 関数の戻り値が Unicode として適切な値を返さないためです。VBA で は、2. のように AscB 関数を使用しなければいけません。2. の記述では、Unicode
の 2 バイト目の値 (&H30) が取得できます。Access Basic と同じ結果を得るには、 3. のように、StrConv 関数を使って、Unicode 文字をシステムの既定のコード ペー ジ内の文字へ変換します。

    Print Hex(Asc(MidB("あ", 2, 1))) ‘ 結果 A0
    Print Hex(AscB(MidB("あ", 2, 1))) ‘ 結果 30
    Print Hex(AscB(MidB(StrConv("あ", vbFromUnicode), 2, 1))) ‘ 結果 A0 

### 文字コードから文字を取得する
システムの既定のコード ページ内の文字コードから文字を取得するには、Chr 関数を 使用します。また、Unicode から文字を取得するには、ChrW 関数を使用します。
どちらのコードを扱っているのかによって、使い分ける必要があります。

- システムの既定のコード ページ内の文字コードから文字を取得         Chr 関数
- Unicode から文字を取得                                       ChrW 関数

例えば、"あ" という文字は、それぞれ次のように記述することで取得できます。
```vb
  Print Chr(&H82A0)
  Print ChrW(&H3042)
```
VBA では、Chr 関数は Unicode 文字を返します。つまり、必ず 2 バイト文字を返しま す。次の例のように、Chr 関数の返す文字のバイト数が、Access Basic と異なる場合 があるので注意が必要です。
```vb
  Print LenB(Chr(&H41))     ‘ Access Basic    1
                            ‘ VBA             2
```
1 バイト文字を結合して 2 バイト文字を取得するような場合には、ChrB 関数を使用し ます。ここでも、システムの既定のコード ページ内の文字コードと Unicode の違いを 考慮する必要があります。例えば、"A" という文字は、Access Basic と VBA でそれぞ れ次のように表します。
```vb
  Print Chr(&H41)                                        ‘ Access Basic
  Print ChrB(&H41) & ChrB(&H0)                           ‘ VBA
  Print StrConv(ChrB(&H41) ,vbUnicode)                   ‘ VBA
```
また、"あ" という文字は、次のように表せます。
```vb
  Print Chr(&H82) & Chr(&HA0)                            ‘ Access Basic
  Print ChrB(&H42) & ChrB(&H30)                          ‘ VBA
  Print StrConv(ChrB(&H82) & ChrB(&HA0) ,vbUnicode)      ‘ VBA
```
### ファイル I/O
ファイルからデータを読み込む関数として Input 関数、InputB 関数があります。Input 関数は、文字をファイルから読み込むときに、Unicode 文字列に変換します。それに対 して、InputB 関数は、データをバイナリデータとしてみなして、Unicode への変換をお こないません。
例えば、次のサンプルデータのように、固定長のフィールドで格納されているファイル を、InputB 関数を使って読み込む時には、固定バイト長のデータを読み込んでから
Unicode へ変換して表示します。

  サンプルデータ (sample.dat)
     123456789012345678901234567890
     名前     住所      電話

  サンプルプログラム
```vb
    Dim dat1 As String, dat2 As String, dat3 As String
    Open "sample.dat" For Input As #1
    dat1 = StrConv(InputB(10,#1), vbUnicode)
    dat2 = StrConv(InputB(10,#1), vbUnicode)
    dat3 = StrConv(InputB(10,#1), vbUnicode)
```
### バイト データ型の利用
VBA では、新しいデータ型としてバイト型 (Byte) が追加されています。バイナリデー タを操作する際に文字列変数を使うと入出力時に ANSI - Unicode 変換がおこなわれて バイナリ データが変更されてしまいます。バイナリ データを扱う場合はバイト型の変数を利用するようにしてください。
```vb
    Dim ByteData() As Byte
    ByteData = "文字列"                       ' Unicode 形式で格納される。
    ByteData = StrConv("文字列", vbUnicode)   ' ANSI 形式で格納される。
    ByteData = InputB(10, #1)                 ' バイナリデータが格納される。
    Debug.Print ByteData(5)                   ' 配列としてデータを操作可能。
    例）
      Public Function Test2()
      Dim ByteData() As Byte
        ByteData = StrConv("ABCDEFG", vbFromUnicode)  ' ANSI に変換
        Test2 = Chr(ByteData(5))
      End Function
```

プロパティ
文書番号: 404928 - 最終更新日: 2004年10月4日 - リビジョン: 1.2
この資料は以下の製品について記述したものです。

Microsoft Access 2000 Standard Edition
Microsoft Access 97 Standard Edition
Microsoft Access 95 Standard Edition

キーワード: 
2byte 9.0 ac95 ac97 acc2000 acc9 function kbinfo unicode vba 文字列 関数 KB404928

# INFO: Asc/AscB/AscW と Chr/ChrB/ChrW の間の関数の違い
[INFO: Asc/AscB/AscW と Chr/ChrB/ChrW の間の関数違い](https://web.archive.org/web/20070317223248/http://support.microsoft.com/kb/145745/ja)

http://support.microsoft.com/kb/145745/ja

## 概要
何年もの間、BASIC プログラマーは Asc 関数と Chr 関数を使用して ASCII 文字セットにアクセスし、操作してきました。主流のオペレーティング システムとアプリケーションで Unicode(以下、UTF-16(LE)の意味） が受け入れられるようになったため、Asc 関数と Chr 関数の改良版が必要になりました。この要求を満たすために、Windows 用の Microsoft Visual Basic (4.0 以降) には、AscB/ChrB および AscW/ChrW 関数が含まれています。

## 詳細
Unicode は、文字を数値形式でエンコードするための ANSI 標準を置き換えるように設計された標準です。 ANSI 標準では各文字を表すのに 1 バイトしか使用しないため、最大 256 の異なる文字に制限されています。これは、英語を話す聴衆のニーズには十分ですが、世界のソフトウェア市場を考慮すると不十分です。 Unicode 標準では、各文字は 2 バイトで表されるため、Unicode 文字セット全体には 65,536 文字を収めることが可能です。

Microsoft Windows NT、Microsoft Windows 2000、および Microsoft OLE 2.0 は完全に Unicode ベースであり、Visual Basic (4.0 以降) はすべての文字列を内部的に Unicode 形式で表します。 AscW 関数と ChrW 関数を使用すると、Unicode 文字の全範囲にアクセスできます。これらの関数は、0 ～ 255 ではなく 0 ～ 65,535 の引数をサポートする点を除いて、元の Asc および Chr 関数と同じように機能します。多くの Visual Basic オブジェクト (デバッグ ウィンドウ、ラベル、テキスト ボックスなど) は、 Unicode文字を表示できない場合「？」で表示されます。

現在、すべての文字列は内部的に Unicode 形式で表現されているため、バイナリ データを文字列で表現するのは以前ほど単純ではありません。 Chr 関数を使用してデータを文字列に代入すると、以前と同じ動作になりません。例えば：

```vb
stringvar = Chr(65)
```
バイト 1 の値は 65 で、バイト 2 の値は 0 です (これは文字 "A" の Unicode 表現です)。 ANSI から Unicode への変換は、この場合のように値がゼロの 2 番目のバイトを追加するだけであるとは限らないことに注意してください。たとえば、130 ～ 159 の範囲の ANSI 文字コードのほとんどは、まったく異なる Unicode 値を持っています。 「Debug.Print AscW(Chr(130))」を実行してみると、値 8218 が表示されます。

現在、Microsoft Windows ではリトル エンディアン プロセッサが必要です。つまり、複数バイトのエンティティでは、最初のバイトが最下位であり、後続のバイトで重要度が高くなります。これは、Unicode 文字 "A" が内部的に次のように表される理由を説明しています。

```text
   -------------------
   |   65   |    0   |
   -------------------
     byte 0     byte 1
```

AscB 関数と ChrB 関数を使用すると、Asc 関数と Chr 関数で実行されていた機能を置き換えること(replicate)ができます。これらの関数では 1 バイトの単位を操作できるためです。 65、66、67、および 68 のバイナリ値が連続する 4 バイトの文字列が必要な場合、Chr 関数を使用しても機能しません。代わりに ChrB 関数を使用する必要があります。例えば：

```vb
stringvar = ChrB(65) & ChrB(66) & ChrB(67) & ChrB(68)
```
また、機能を使用して新しいバイト データ型の配列を作成およびことに、バイナリ データを操作することができます。
さらにこの情報を明確にこれらの関数の簡単な使用の結果の説明は下の一覧に表示されています。

#### `Asc(Chr(255))`
Print Asc(Chr(255)) --> "255" 

~~何もここでは、Chr 関数は、Unicode 文字を返すことを除いてを 2 バイトを占有する 1 バイトの ANSI 文字の代わりに新しい。~~
Chr 関数が 1 バイトの ANSI 文字ではなく 2 バイトを占める Unicode 文字を返すことを除いて、ここで新しいことは何もありません。

#### `Asc(ChrB(255))`
~~--Asc(ChrB(255)) 印刷 > 5 - 無効なプロシージャ呼び出しです。~~

Print Asc(ChrB(255)) --> 5 - Invalid procedure call. 

This usage returns an error because the Asc function always expects at least a two-byte parameter and the ChrB function is only returning a single byte. 
~~この使用率は Asc 関数は、常に、少なくとも 2 バイトのパラメーターを受け取るため、ChrB 関数は 1 バイトを返すだけエラーを返します。~~
Asc 関数は少なくとも 2 バイトのパラメーターを常に受け取ることを想定しているにも関わらず、ChrB 関数は常に 1 バイトしか返さないため、この使用法ではエラーが返されます。
#### ` Asc(Chr(256))`
Print Asc(Chr(256)) --> 5 - Invalid procedure call.
Although the Chr function returns a two-byte Unicode character, it still only takes numbers between 0 and 255 for its argument (note that on a DBCS enabled system, Asc/Chr handle two-byte DBCS characters, converting them to and from Unicode). Using the ChrW function allows access to the full 65,536 Unicode character locations. 

~~Chr 関数は、2 バイトの Unicode 文字を返します、0 ～ 255 の引数 (注意 DBCS が有効になっているシステムで昇順/Chr 処理する 2 バイトの DBCS 文字、Unicode を変換する)、数値だけがかかります。 アクセスを完全 65, 536 の Unicode 文字の場所を許可する ChrW 関数を使用します。~~

Chr 関数は 2 バイトの Unicode 文字を返しますが、引数として 0 から 255 までの数字しか取りません (DBCS が有効なシステムでは、Asc/Chr は 2 バイトの DBCS 文字を処理し、Unicode との間で変換することに注意してください)。 ChrW 関数を使用すると、65,536 個の Unicode のコードポイントすべてにアクセスできます。

#### `AscW(ChrW(256))`
Print AscW(ChrW(256)) --> "256" 

これは、このセクションで、最初のステートメントの新しいバージョンです。 ChrW 関数は 0 から 65, 536 の値を受け取り (32 ビット システム) でその文字を返します。 AscW 関数は、この 2 バイト文字を Unicode 文字として解釈し、正しい文字の Unicode 値を返します。

Print Asc(ChrW(256)) --> "65"
Print Asc(ChrW(5000)) --> "63" 

~~ChrW 関数は最初に評価されることは事態です。 ChrW(256) は、文字"A"と、関数が Asc("A") に減少するための"A"は Unicode (および ANSI) 数が 65。 Visual Basic は Chr(5000) だけを表示で表される文字を表示することを認識しないため、"しますか?"、ANSI と Unicode の値が期待どおりと"しますか?"は 63。~~
ここで起こっていることは、ChrW 関数が最初に評価されているということです。 ChrW(256) は文字 "A" であるため、関数は Asc("A") に縮小され、"A" の Unicode (および ANSI) 番号は 65 です。Visual Basic は文字の表示方法を認識していないためです。 Chr(5000) で表される場合、「?」が表示されるだけで、予想どおり、「?」の Unicode および ANSI 値が表示されます。は63です。

Print AscB(Chr(65)) --> "65"
Print AscB(ChrW(256)) --> "0"
Print AscB(ChrW(257)) --> "1"
Print AscB(ChrW(555)) --> "43"
Print AscB(ChrW(65535)) --> "255" 

~~これらすべての返す各文字は内部で表されます方法を理解によって値が説明されることができます (上記のリトル エンディアンの参照を参照) して受信した文字の最初のバイトにのみ、AscB 関数を検索するという事実です。 視覚的に次の図は、外観します。~~
これらの戻り値はすべて、各文字が内部でどのように表現されるか (上記のリトル エンディアンのリファレンスを参照) を理解し、AscB 関数が受け取った文字の最初のバイトのみを参照するという事実によって説明できます。視覚的には、次の図のようになります。
```vb
             -------------------
   Chr(65)   |   65   |    0   |
             -------------------
   Chr(256)  |    0   |    1   |
            -------------------
   Chr(257)  |    1   |    1   |
             -------------------
   Chr(555)  |   43   |    1   |
             -------------------
   Chr(65535)|   255  |  255   |
             -------------------
               byte 0    byte 1
				
```
AscB 関数は、文字が何であれ、最初の1Byteだけ返します。

Print ChrB(65) --> "" 
ChrB 関数は 1 バイトの文字列しか返さないため、Visual Basic はこの ChrB 関数の呼び出しに対して何も出力しません。このような 1 バイト文字列は、有効な Unicode 文字 (または一連の文字) を構成しないため、Visual Basic にとっては何の意味もありません。
Print ChrB(65) & ChrB(0) --> "A" 

この場合、2 つの 1 バイト文字列を 1 つの 2 バイト文字列に連結しています。結果のビット パターンは Unicode "A" のビット パターン(編注:素直に表記を読むと`&H6500`だが、UTF-16LEのため`&H0065`)と同じであるため、Visual Basic はそれを出力します。

---

# 補足
## 固定長型について
[Dim ステートメント](https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/dim-statement)
[【VBA】可変長文字列と固定長文字列 ](https://atelierkobato.com/string/)

```vb
Dim bufLength As String * 20
```
これは20バイトの意味となり、半角(1Byte文字）は20文字入る。UTF-16LEで処理しているからといって10文字しか入らないことはない。
つまり、代入する前はANSIということもある。
次に固定長の文字列は以下の制限からフィールドごとに宣言すべきだとわかる。
[固定長データまたは静的データの大きさが 64K を超えることはできません](https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/fixed-or-static-data-can-t-be-larger-than-64k)

配列の場合の固定長とは
[配列の宣言と固定長配列、動的配列 ](https://www.239-programing.com/excel-vba/basic/basic035.html)
```vb
Dim ar(1 to 20. 1 to 50) As Integer
```
のように<b>要素の数</b>が固定されている
```vb
  Dim StringArray(10) As String * 12
```
こういうのは可能だが、

```vb
  Dim MyForm As Object    ' Because MyForm is Object, binding is late. 
  Set MyForm = New Form1 
  Dim StringArray(10) As String * 12 
  ' The next line generates the error. 
  MyForm.MyProc StringArray 
```

[固定長文字列の配列またはユーザー定義型の配列を、バリアント型の変数に割り当てることはできません](https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/can-t-assign-or-coerce-array-of-fixed-length-string-or-user-defined-type-to-vari)という制約がある。
このように固定長配列は制約が多く、今ではあまり使われないのだが、文中には出てくるので補足した。

## Accessの具体例
https://web.archive.org/web/20150709141708/accessclub.jp/bbs5/0038/vba12081.html
AccessClub Tips Forum
<blockQuote>
タイトル	： LeftB、MidBの文字列操作について
記事No	： 12081
投稿日	： 2008/09/16(Tue) 22:44
投稿者	： わい

  OS:Windows XP
  Access Version:2003

  いつもお世話になります。

  簡単なことかもしれませんが、教えてください。
  Access VBAの中で文字列を操作していたのですが、うまくいかなくて…。

  「ABCDEあいうえお」と半角と全角が文字列があってそれを以下のようにバイト数で認識させます。
  Lenb(StrConv("ABCDEあいうえお", vbFromUnicode))
  で、結果15バイトなんですけど、それをLeftBなりMidBなりでバイト数でその文字を抜き出ししたいんです。
  たとえば5バイト目から3バイトを抜き出したくて。
  MidB("ABCDEあいうえお", 5, 3)？？だとうまくいかないんですが、結果「Eあ」って文字列を抜き出ししたいんです。

  どうしたらいいんでしょうか。
  よろしくお願いします。
タイトル	： Re: LeftB、MidBの文字列操作について
記事No	： 12082
投稿日	： 2008/09/16(Tue) 23:07
投稿者	： akuseku

  MidB関数もLenB関数と同じようにANSI文字列に変換した値を渡し、
  MidB関数の戻り値をまたUnicode文字列に変換します。

  [ACC2000] Unicode と文字列操作関数の留意点
  http://support.microsoft.com/kb/404928/ja

  StrConv 関数 - Access - Microsoft Office Online
  http://office.microsoft.com/ja-jp/access/HA012289151041.aspx

タイトル	： Re^2: LeftB、MidBの文字列操作について
記事No	： 12083
投稿日	： 2008/09/16(Tue) 23:29
投稿者	： わい

  さっそくありがとうございました。
`  moji = MidB(StrConv("ABCDEあいうえお", vbFromUnicode), 5, 3)`
`   StrConv(moji, vbUnicode)`で"Eあ"になりました。
  ありがとうございました。
</blockQuote>
## ExcelのワークシートのLENBとVBAのLENB
https://www.moug.net/tech/exvba/0140023.html
> このうち、LENB関数はVBAのLenB関数と異なり、半角文字は1バイト、全角文字を2バイトとしたバイト数を返します。


## [留意]サンドボックスモードでエラーになる関数がある
発掘とはそれだけではなく、現在の流れにアップツーデートすることも大事だろう。
[サンドボックス モードでブロックされる Access の関数とプロパティ](https://support.microsoft.com/ja-jp/office/%E3%82%B5%E3%83%B3%E3%83%89%E3%83%9C%E3%83%83%E3%82%AF%E3%82%B9-%E3%83%A2%E3%83%BC%E3%83%89%E3%81%A7%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF%E3%81%95%E3%82%8C%E3%82%8B-access-%E3%81%AE%E9%96%A2%E6%95%B0%E3%81%A8%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3-9a829783-f7a8-4a9f-8d43-8650b8cc9565)
> この記事では、サンドボックス モードで許可およびブロックされる関数とプロパティに関するリファレンス情報を Access。 Access では、MonthNameやStrReverseを含むいくつかの新しい関数をサンドボックス モードで実行できます。また、Assistance、ExportNavigationPane、LoadCustomUI などの複数の関数がブロックされます。 この記事の情報を使用するには、データベースを信頼する (コンテンツを有効にする) か、信頼できる場所にデータベースを配置する必要があります。

この記事中でエラーになるものとしてInputBがある。