Excel VBA Excel 2013 Later セルに入っている文字のコードを UTF-16LE UTF-8 EUC-jp Shift-Jisに変換してイミディエイトに出力する

# 令和の時代の文字コード変換
今回[ADODB.Streamによる文字コード変換のサンプル(VB6) -NonSoft](http://nonsoft.la.coocan.jp/SoftSample/SampleModADOS.html)の記事を参考にしている。この記事はVBAに完全に移植できるか自身がないのと、UTF-7は使ったことがないため、省略できると考えられた。また[Tipsfound › Excel VBA › Unicode 文字の入力や読み込み](https://www.tipsfound.com/vba/04012)を利用してADODBの使用回数を減らした。
さらに
CreateObjectを使って参照設定をナシにした。

##ほんとにUTF-16？UTF-16LEでは？
[Tipsfound › Excel VBA › Unicode 文字の入力や読み込み](https://www.tipsfound.com/vba/04012)
ではVBAの中のコードはUTF-16としている。
しかし、UTF-16の割りにZBOMがつくことがない。またサロゲートペアを取ると、ひっくり返っていることが判る。
このためUTF-16ではなくUTF-16LEみたいだ。
[UTF-16 が単に Unicode と呼ばれることがある理由](http://yanok.net/2016/03/utf-16-unicode.html)
>なので前世紀に書かれた文書やプログラムでは「Unicode = UCS-2」という前提があり、それを漫然と引き継いでいると、「Unicode」と言っているのが実質的にはUTF-16を指していることがあるわけです。
そして現在
今では個別の符号化方式としては「UTF-16」「UTF-8」のように言った方が適切なことは言うまでもありません。ただ、UTF-16の意味で「Unicode」と言われることがあるのは、単なる無知や誤解ではなく、それなりに過去の経緯が影響しているのだということです。

Windowsの標準がUTF-16であり、歴史的な経緯から（そもそも最初のUnicodeが）UTF-16だったため、メモ帳ではUnicodeと言っているという。

[Unicodeのサポート](https://docs.microsoft.com/ja-jp/cpp/text/support-for-unicode?view=msvc-160)
>Unicode は、1バイトでは表現できない文字セットを含む、すべての文字セットをサポートするための仕様です。 国際市場向けにプログラミングしている場合は、Unicode またはマルチバイト文字セット(MBCS) のいずれかを使用することをお勧めします。 または、スイッチを変更することによってビルドできるようにプログラムをコーディングします。
ワイド文字は、2 バイトの多言語文字コードです。 世界中の最新のコンピューティングで使用されているほとんどすべての文字 (技術記号や特殊な公開文字を含む) を含む、数十の文字が、Unicode 仕様に従って、UTF-16 を使用してエンコードされた1つのワイド文字として表すことができます。 1つのワイド文字では表現できない文字は、unicode サロゲートペア機能を使用して、Unicode ペアで表すことができます。 一般的に使用されるほとんどすべての文字は、1つの16ビットワイド文字で UTF-16 で表されるため、ワイド文字を使用すると、国際文字セットを使用したプログラミングが簡単になります。 ***16LE (リトルエンディアン用) を使用してエンコードされたワイド文字は、Windows のネイティブ文字形式です。***
ワイド文字列は`wchar_t[]`配列として表現され、`wchar_t*`ポインターで指し示されます。 ASCII 文字は、先頭に文字 L を付けることで、ワイド文字として表現できます。 たとえば、`L'\0'` はワイド文字 (16 ビット) の終端の`NULL`文字です。 同様に、ASCII 文字列リテラルは、ASCII リテラルの先頭に文字 L を付けることで、ワイド文字列リテラルとして表現できます (`L"Hello"`)。
通常、ワイド文字はマルチバイト文字よりもメモリ内の領域を多く必要としますが、処理は速くなります。 さらに、マルチバイトエンコードで一度に表現できるロケールは1つだけです。一方、世界中のすべての文字セットは、Unicode 表現によって同時に表現されます。

マイクロソフトの公式はこのように説明している。あとのメインでは使っていないが、UTF-16に変換する関数が下記である。

```vb
Function UTF16EEEFbyte(s As String) As Byte()
' 文字列をUTF-16のバイト配列に変換する。
' BOMは本来は除去する。 LE並びの場合はEE EF
' モジュールレベルのプライベート変数と定数、Sub プロシージャ使用
' Dim sr As New ADODB.Stream
Dim textBuf16LE As String
Dim var
Call CreateObjectADODB
With sr
.Charset = "Utf-16"
.LineSeparator = adCrLf
.Type = adTypeText
.Open
.WriteText s, adWriteChar
.Position = 0 ' Binaryに変換するため0位置にする。
.Type = adTypeBinary
' .Position = 2 ' BOMを示すために、コメントにしているが、本当に使う場合にはこちらも使う。先頭の2ByteのBOMをSkipする。
UTF16EEEFbyte = .Read(-1)
Call GarbageADODB
End With
End Function
```

なお、上記のMBCS文字はレガシーで古い技術としている。[マルチバイト文字セット (MBCS) のサポート](https://docs.microsoft.com/ja-jp/cpp/text/support-for-multibyte-character-sets-mbcss?view=msvc-160)

実際に、これで「あ」を示すと `EE EF 30 42`となり、ひっくり返っていることが判る。このため、LEではある。調べてみると、UTF-16はBOMがついているため、このBOMによりBEとLEとどっちにもなる。このBOMがついていないLEならびがWinodowsの標準である。
とここまでは分かったのだが、VBAに限れば、StrConvでもBOMはつかないので、UTF-16LEまたはANSIになる。それはCP932だとかShift-JisだとかWindows3.1-Jだとか非難轟々であるが、一応ANSIとしておく。
[WindowsがUTF-8(BOMなし) を標準に](https://chienomi.org/archives/digi/software/1888)
>長かった…

>Windows 10 Insider Preview Build 18298（19H1） でメモ帳がUTF-8(BOMなし)に対応し、これをデフォルトとした。

##セルから文字列を代入すると、UTF-16LEらしい

ア
ｱ
アｱ
ʏ
丙
あ
亜
𠮷
セルのA列にこのような文字列を貼り付ける。
ʏは発音記号 https://0g0.org/unicode/028F/

そしてセルを選択する。このとき、
`buf16LE = ActiveCell.Value`
として、セルから文字列の変数に代入することはよくある。
そこで、このとき、セルから入ってくる文字の文字コードはなにか。
これはUTF-16LEらしい。
~~しかし、これはロケールで違うと考えられる。~~
~~その証拠に StrConvにはロケール番号の指定がある。~~
ロケールははひらがな用らしい。

##関数に行くときはUTF-16LEかShift-Jisらしい
確証はないのだが、大枠としてはUTF-16LEで行っている。BOMはついていないからだ。
しかしサロゲートペアを取るとひっくり返っているため、これはUTF-16LEらしい。
しかし、半角英数字はShift-Jisらしい。
このため、ExcelのVBAは文字列のコードがなにか判定しているらしい。もしくは内部処理はUTF-16LEになっているようだ。
さらに、このどちらかはExcelが決めている。
このため、UTF-16LEであることを固めるため、関数側で
`StrConv(s, 128)`のような変換をする必要ない。
やると文字コードが変わってしまう。

## ADODB.Streamの文字コードの変換の流れ
このようにUTF-16LEで関数に入ってきた文字列をADODB.Streamが変換する過程を見ておく。

```vb
With sr
.LineSeparator = -1 ' adCRLF
.Type = 2 ' adTypeText
.Charset = "EUC-JP"
.Open
.WriteText s, 0 ' adWriteChar 'そのままだとS-Jisの場合があるためUTF-16LEに明示的に変換して書き込むことはしない（たぶん変換されている)Strconv(vbunicode）の結果はおかしい
.Position = 0
.Type = 1 'adTypeBinary
EUCbyte = .Read(-1)
```
###定石としてはOpenの前に改行、タイプ、文字コードを決めるが、逆でも良い。
NonSoftのサンプルはOpenをしてから文字コードを決めている。

```vb
objStm.Open
objStm.Type = adTypeText
objStm.Charset = cset
objStm.WriteText strUni
```

こんな感じで、Openしてから文字コードなどを決定している。
このあとのバイナリ変換等を考えればOpenしてからでも設定は可能でないとできなくなってしまうのでこれでも正解だと言える。

###文字コードの変換は特に命令がない
関数に入ってきた文字コードはUTF-16LEかShift-Jisらしいが、Adodb.Streamは

```vb
With sr
.Open
.Type = 2  ' --- テキストの指定
.Charset = "EUC-JP"
.WriteText s, 0 ' adWriteChar 
```

このように文字コードを指定するだけでUTF-16LEは別の文字コード体系に変換されてしまう。

###バイナリ変換はポジション0にしてタイプを変える2ステップ、順番は厳密だが特別な命令はない

```vb
.Position = 0
.Type = adTypeBinary
```

この順番には注意が必要で0にしてからTypeの変更を行う。
そうしないとエラーになってしまう。
ここは順番が決まっている。

### 復号を考えない場合にはBOMを飛ばす
NonSoftによるとUTF-16BE,UTF-16LEはBOMがないが、UTF-16（UNICODE）はBOMが2バイトとしている。
UTF-8は3バイト。
復号を考えると飛ばすのはまずい気もするが、UTF-8の復号はBOMが飛ばされていても可能だった。

######UTF-8の復号


```vb
Function UTF8ByteToString(bb() As Byte) As String
' UTF-8のバイナリから作成されたバイト配列を参照して、UTF-8の文字列に変換する
Dim ConvertStr As String
'Dim sr As New ADODB.Stream
Call CreateObjectADODB
With sr
.Type = adTypeBinary
.Open
.Write bb 'bbにはカッコがつかない。これで書き込まれる
.Position = 0 'Positionをゼロに戻す
.Type = adTypeText 
.LineSeparator = adCLf ' BOMは削っているが、テキストに変換する際に再度付与されるらしい。
.Charset = "UTF-8" ' この3行でUTF-8へ変換がされる(.LineSeparatorはなくても良い）
UTF8ByteToString = .ReadText(adReadAll)
Call GarbageADODB
End With
End Function
```

####ISO-2022-jpは先端と終端を飛ばす
またISO-2022-jpは前後に終端記号がついている。
しかし、半角英数等はついていない。
ここはエスケープコード`&H1B`が最初にあるかどうかで判定している。

### Readをバイト配列で受けとる
そしてバイナリに変換したものを配列に入れる。
これを関数の値として出力し、Adodb.Streamを終了させる。
ADODB.Streamの変数の宣言をモジュールレベルで行い、CreateObjectとNothingをモジュールレベルの
プライベートSub　プロシージャで行い、参照設定を回避するとともに、若干すっきりさせた。

##コード全体（モジュールレベル）
プライベートを使用しているので、基本的に1つの標準モジュールを新たに作って、貼り付けてください。

```vb
Option Explicit
' モジュールレベルのプライベート定数と変数を宣言
' 2020/11/27
Private Const adCrLf = -1, adCr = 13, adLf = 10
Private Const adTypeText = 2
Private Const adTypeBinary = 1
Private Const adWriteChar = 0, adWriteLine = 1
Private Const adSaveCreateOverWrite = 2, adSaveCreateNotExist = 1, adWriteLine = 1 ,adReadLine = -2, adReadAll = -1
Private sr As Object

Sub ShowCharacterCodeOnImmediate()
' Excel 2013 Later
' 選択しているセルに入っている文字のコードをイミディエイトに表示する
' UTF-8は復号を試みる
' Unicode関数の結果を表示する
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = ActiveSheet
Dim buf16LE As String
Dim bufS_Jis As String
Dim bb16LE() As Byte
Dim bbS_JIs() As Byte
Dim bbU8() As Byte
Dim bbu8str As String
Dim bbEUCjp() As Byte
Dim sEUCJp As String
Dim i As Long
'日本語カタカナ全角ア Shift-Jis &H8341 UTF16-LE &H30A2
buf16LE = ActiveCell.Value
'buf16LE = "あ"
On Error Resume Next
Debug.Print "ASCW" & vbTab & Hex(AscW(StrConv(buf16LE, vbFromUnicode)))
Debug.Print "UNICODEFunction " & vbTab & Hex(WorksheetFunction.Unicode(buf16LE))
On Error GoTo 0
bb16LE = buf16LE
bufS_Jis = StrConv(buf16LE, vbFromUnicode) 'セルの文字はUT-16LE vbFromUnicode で UTF-16LEからS-Jisへ変換
bbS_JIs = bufS_Jis
bbU8 = UTF8byte(buf16LE)
If IsUpperSarrogateCharacter(buf16LE) Then
' 上位サロゲートと判定できればサロゲートペアとして表示する
  Debug.Print "UTF-16LE" & vbTab & "&H" & CStr(Hex(AscW(Mid(buf16LE, 1, 2))) & "&H" & CStr(Hex(AscW(Mid(buf16LE, 2, 2)))))
Else
  Debug.Print "UTF-16LE" & vbTab & Hex(bb16LE(1)) & vbTab & Hex(bb16LE(0)) ' ア 30A2 UTF-16 1,0の並びなのでUTF-16LE
End If
sEUCJp = ""
For i = LBound(bbS_JIs) To UBound(bbS_JIs)
 sEUCJp = sEUCJp & Hex(bbS_JIs(i))
Next
Debug.Print "S_JIS" & vbTab & sEUCJp
For i = LBound(bbU8) To UBound(bbU8)
 bbu8str = bbu8str & Hex(bbU8(i)) & vbTab
Next
Debug.Print "UTF8に変換したコード" & vbTab & bbu8str
Debug.Print "UTF8に変換したコードを復号" & vbTab & UTF8ByteToString(bbU8)
sEUCJp = ""
bbEUCjp = EUCbyte(buf16LE)
For i = LBound(bbEUCjp) To UBound(bbEUCjp)
 sEUCJp = sEUCJp & Hex(bbEUCjp(i)) & vbTab
Next
Debug.Print "EUC-Jp" & vbTab & sEUCJp
Erase bbEUCjp: sEUCJp = ""
bbEUCjp = ISO2022jpbyte(buf16LE)
For i = LBound(bbEUCjp) To UBound(bbEUCjp)
 sEUCJp = sEUCJp & Hex(bbEUCjp(i)) & vbTab
Next
Debug.Print "ISO2022jp" & vbTab & sEUCJp
'Debug.Print Hex(UTF8byte(0)) & vbTab & Hex(UTF8byte(1)) & vbTab & UTF8byte(2)
End Sub

Function EUCbyte(s As String) As Byte()
' 参照した文字列をEUCのバイト配列に変換
' モジュールレベルのプライベート変数と定数、Sub プロシージャ使用
' http://euc.jp/i18n/charcode.ja.html
' Dim sr As New ADODB.Stream
Dim srbb() As Byte
Dim textBuf16LE As String
Dim var
Call CreateObjectADODB
With sr
  .LineSeparator = adCrLf
  .Type = adTypeText
  .Charset = "EUC-JP"
  .Open
  .WriteText s, adWriteChar ' そのままだとS-Jisの場合があるためUTF-16LEに明示的に変換して書き込むことはしない（たぶん変換されて  いる)Strconv(vbunicode）の結果はおかしい
  .Position = 0
  .Type = adTypeBinary
  EUCbyte = .Read(-1)
  Call GarbageADODB
End With
End Function

Function ISO2022jpbyte(s As String) As Byte()
' 参照した文字列をISO2022-JPのバイト配列変換
' 先端と終端がある場合には1Bをエスケープ文字として削除する
' モジュールレベルのプライベート変数と定数、Sub プロシージャ使用
' Dim sr As New ADODB.Stream
Dim srbb() As Byte
Dim textBuf16LE As String
Dim var
Dim i As Long
Dim iSize As Long
Call CreateObjectADODB
With sr
.LineSeparator = adCrLf
.Type = adTypeText
.Open
.Charset = "iso-2022-jp" '1B 28 42 US-ASCIIに切替 1B 24 42 Jis X 0208に切替 Jis X 0208に切替1B=ESC (B
.WriteText s, adWriteChar ' adWriteChar 'そのままだとS-Jisの場合があるためUTF-16LEに明示的に変換して書き込む
.Position = 0
.Type = adTypeBinary
srbb = .Read(-1)
If srbb(0) = Val("&H1B") Then ' 1Bはエスケープ文字
iSize = .Size
.Position = 3 '最初の3バイトを除く
ISO2022jpbyte = .Read(iSize - 6) '最初の3バイトと終端の3バイトを除く
Exit Function
Else
ISO2022jpbyte = srbb
Exit Function
End If
End With
Call GarbageADODB
End Function

Function UTF8byte(s As String) As Byte()
' 文字列をUTF-8のバイト配列に変換する。
' BOMは除去する
' モジュールレベルのプライベート変数と定数、Sub プロシージャ使用
' Dim sr As New ADODB.Stream
Dim textBuf16LE As String
Dim var
Call CreateObjectADODB
With sr
.Charset = "Utf-8"
.LineSeparator = adCrLf
.Type = adTypeText
.Open
.WriteText s, adWriteChar
.Position = 0
.Type = adTypeBinary
.Position = 3 'BomをSkip
UTF8byte = .Read(-1)
Call GarbageADODB
End With
End Function

Function UTF8ByteToString(bb() As Byte) As String
' UTF-8のバイナリから作成されたバイト配列を参照して、UTF-8の文字列に変換する
' モジュールレベルのプライベート変数と定数、Sub プロシージャ使用
' Dim sr As New ADODB.Stream
Dim ConvertStr As String
Call CreateObjectADODB
With sr
  .Type = adTypeBinary
  .Open
  .Write bb 'bbにはカッコがつかない。これで書き込まれる
  .Position = 0 'Positionをゼロに戻す
  .Type = adTypeText
  .LineSeparator = adCrLf ' BOMは削っているが、テキストに変換する際に再度付与されるらしい。
  .Charset = "UTF-8" ' この3行でUTF-8へ変換がされる(.LineSeparatorはなくても良い）
  UTF8ByteToString = .ReadText(adReadAll)
  Call GarbageADODB
End With
End Function

Private Function IsUpperSarrogateCharacter(s As String)
' UTF-16 LEのサロゲートペアの判定
If Hex(AscW(s)) >= Hex(&HD800) And Hex(AscW(s)) <= Hex(&HDBFF) Then
  IsUpperSarrogateCharacter = True: Exit Function
Else
  IsUpperSarrogateCharacter = False: Exit Function
End If
End Function

Private Function IsLowerSarrogateCharcter(s As String)
' UTF-16 LEの下位サロゲートペアの判定
Dim bb() As Byte
If IsUpperSarrogateCharacter(s) = True Then
  bb = s
  'Debug.Print Hex("&H" & bb(3) & bb(2))
  If Hex("&H" & bb(3) & bb(2)) <= Hex(&HDC00) And Hex("&H" & bb(3) & bb(2)) <= Hex(&HDFFF) Then
    IsLowerSarrogateCharcter = True: Exit Function
  Else
    IsLowerSarrogateCharcter = False: Exit Function
  End If
End If
End Function

Private Sub CreateObjectADODB()
' モジュールレベルのプライベート変数にADODB.Streamを代入して使用可能にする
 Set sr = CreateObject("ADODB.Stream")
End Sub

Private Sub GarbageADODB()
' ADODB.Streamを終了させる
 On Error Resume Next
 sr.Close
 If Not sr Is Nothing Then Set sr = Nothing
End Sub
```

#おまけ
[そろそろWindowsでUTF-16とShift-JISの変換方法をC++erらしくまとめようか](https://qiita.com/yumetodo/items/453d14eff41b805d8fc4)
VBAも複雑だが、C++になるともっと複雑。WINAPIで引っ張れるし、セルから持ってくるのはUTF-16LEかANSIなのでここまで複雑にならない。
たしかに一つの関数でBOMなどから判定するというのも便利ではあるが、やはり関数がかなり複雑になってしまう。

##Linuxのような改行の変換にADODB.Streamは1つでいいかも

[VBAでUTF-8のファイルをShift-JISに変換する vbabeginner.net](https://vbabeginner.net/vba%E3%81%A7utf-8%E3%81%AE%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92shift-jis%E3%81%AB%E5%A4%89%E6%8F%9B%E3%81%99%E3%82%8B/)
LinuxはUTF-8N、LF改行のテキストファイルのようです。すると、ADODB.Streamは2ついらないようです。
[EOS および LineSeparator プロパティと SkipLine メソッドの例 (VB)](https://docs.microsoft.com/ja-jp/sql/ado/reference/ado-api/eos-and-lineseparator-properties-and-skipline-method-example-vb?view=sql-server-ver15)
ただし、1度ReadText(adReadAll)で文字列型変数に読み込ませて一度閉じて開き、文字コードを変えて書き込んで保存する。

```vb
Sub Utf8ToSjis(a_sFrom, a_sTo)
' モジュールレベルのプライベート変数と定数、Sub プロシージャ使用
' UTF-8 LF改行のテキストファイルを Shift-Jis adCrLfに変換して保存する
' 未検証
' Excel VBA
Dim buf As String '11/28追加
Call CreateObjectADODB
'// ファイル読み込み
With sr
.Open
.Type = adTypeText
.LineSeparator = adLf
.Charset = "UTF-8"
.LoadFromFile(a_sFrom) : buf = .ReadText(adReadAll)
.Close ' 11/28追加
.Open ' 11/28追加
.LineSeparator = adCrlf ' 改行をここで切り替える
.Charset = "Shift-JIS" ' 文字コードを切り替える
.WriteText buf, adWriteChar ' 11/28追加
'// 保存
'.Position = 0 ' 11/28無効化
' Debug.Print .ReadText(adReadAll)
.SaveToFile(a_sTo, adSaveCreateOverWrite)
Call GarbageADODB
End With
End Sub
```

それでこういうVBAを作っていみました
まず、カレントディレクトリに
c:\hoge\ansi.txt
を作ります。これをExcelの下記のVBAマクロで、
C:\hoge\toUTF8.txt
に変換します。
実験してみると、一度ReadTextで文字列型の変数にいれて、
Closeはせずに
Positionを0にして書き込むと上書きされます。
しかし、それはShift-Jisが2バイト、UTF-8が3バイトというバイト数の差かもしれません。
そのため、 `.Close``.Open`を行います。
なお、Windowsのテキストファイルの改行コードはadCrLfですが、今のメモ帳ではUTF-8の場合、改行コードがCrでもLFでも開けました。

###テキストファイル
ANSI形式、改行コードCrLfで保存してください。
このディレクトリは
`Const tgPath = "c:\hoge\"`
ここで決まっています。環境に合わせて変更してください。


```Ansi.txt
ANSIテキストという触れ込みで作ってみました。
ANSI CODE OK?
```

```vb
Sub ANSITOUTF8NFIle()
' モジュールレベルのプライベート変数と定数、Sub プロシージャ使用
Const tgPath = "c:\hoge\"
Const RFile = "\ansi.txt"
Const WFile = "\toUTF8.txt"
Call CreateObjectADODB
Dim buf As String, var
With sr
.Mode = 3
.LineSeparator = adCrLf
.Type = adTypeText
.Open
.Charset = "Shift-Jis"
.LoadFromFile tgPath & RFile
buf = .ReadText(adReadAll) 'この行を落とさない
.Position = 0
.Close
.Open
.Charset = "UTf-8"
.LineSeparator = adCr '本当は adCrLf 実験のためadCr それでもメモ帳で開ける。
.WriteText buf, adWriteChar
.SaveToFile tgPath & WFile, adSaveCreateOverWrite
.Position = 0
.LineSeparator = adCrLf
.Type = adTypeBinary
.Flush
.Position = 3
var = .Read(adReadAll)
.Close
.Open
.Write var 'Binaryで書き込んでもテキスト形式に保存するとテキスト
.SaveToFile tgPath & WFileN, adSaveCreateOverWrite
.Close
End With
Call GarbageADODB
End Sub
```

###補足
adodb.streamのレジストリを見ると、さらにUnicodeがあった。
このUnicodeに入れると、UTF-16同様BOMがついて並び順がLEになる。
なのでWindows自体がUTF-16LEなのは間違いない。
というのもUTF-16でかつ並び順がLEの場合、レジストリではCodepageは1201でBodyFormatはUNICODEFFFEとなっている。

HKCE\MIME\Database\Codepage\1200
BodyCharset Unicode
Encoding 01 01 00 00
FixesWidhFont Courrier New
PropotionalFont Arial
HKCE\MIME\Database\Codepage\1200
HKCR\MIME\Database\Charset\unicode
のレジストリを見る。
HKCE\MIME\Database\Codepage\1201
BodyCharset UnicodeFFFE FFFEはUTF-16で、かつバイトの並び順はLE
`Shift_Jis`
別名Alias:csWindows31J
Codepage 932
InternetCodePage 932

`UNICODE`
Codepage 1200
InternetCodePage 1200

`UNICODEFFFE`
Codepage 1200
InternetCodePage 1201


`iso-8859-1`
別名Alias:US-ASCII
Codepage 1252
InternetCodePage 1252

`utf-7`
Codepage 1200
InternetCodePage 65000

`utf-8`
Codepage 1200
InternetCodePage 65001

`iso-2022-jp`
Codepage 932
InternetCodePage 50220

`euc-jp`
Codepage 932
InternetCodePage 50220

ADODBの参照するレジストリを見るとインターネットコードページの方が優先されている。
CodePageとInternetCodepage一致しているものは、UNICODEと、Shift-Jisと主要なものだけである。

[Unicode (Visual Basic)](https://docs.microsoft.com/ja-jp/dotnet/visual-basic/language-reference/modifiers/unicode)
>2015/07/20
>Visual Basic では、宣言する外部プロシージャの名前に関係なく、すべての文字列を Unicode 値にマーシャリングする必要があることを示します。

>プロジェクトの外側に定義されたプロシージャを呼び出すと、Visual Basic コンパイラは、プロシージャを正しく呼び出すために必要な情報にアクセスできません。 この情報には、プロシージャの配置場所、識別方法、呼び出し元のシーケンスと戻り値の型、および使用されている文字列の文字セットが含まれます。 Declare ステートメントは、外部プロシージャへの参照を作成し、この必要な情報を提供します。

>Declare ステートメントの charsetmodifier 部分では、外部プロシージャの呼び出し時に文字列をマーシャリングするための文字セット情報を指定します。 これは、Visual Basic が外部ファイルで外部プロシージャ名を検索する方法にも影響します。 Unicode 修飾子は、Visual Basic がすべての文字列を Unicode 値にマーシャリングする必要があり、検索時に名前を変更せずにプロシージャを検索する必要があることを指定します。

>文字セット修飾子が指定されていない場合は、Ansi が既定値になります。


>魔界の仮面弁士  2004-11-24 19:17:37  No: 117735
》GAKUさん
> 便乗質問で申し訳ないんですがADODB.Streamは
ADODB.Stream は、OS の NLS (National Language Support:各国語サポート) の
機能を呼び出しているだけなので、使えるコードに関しては、
 <ファイル> C:\Windows\System32\*.NLS
 <レジストリ> HKEY_CLASSES_ROOT\MIME\Database\
などに登録された情報に依存すると思います。

\# この内容は、Windows および Internet Explore や
\# Office、SNA Server、Host Integration Server などの
\# バージョンによって変化します。

> 半角カナ文字ISO-IR13は扱えないのでしょうか？
ISO-IR13 という物については知らないのですが、それって、
JIS X 0201:片仮名用図形文字集合 (JIS_C6220-1969-jp) と
同じ物なのでしょうか?

http://www.asahi-net.or.jp/~bd9y-ktu/dtd_f/rfc_f/rfc1345j.html

>[RFC1345およびKXS2]
Name: JIS_C6220-1969-jp
Source: ECMA registry
Alias: JIS_C6220-1969
Alias: iso-ir-13
Alias: katakana
Alias: x0201-7
Alias: csISO13JISC6220jp

>もし、JIS X 0201 (いわゆる半角カナ)だとしたら、これは
http://www.nslabs.jp/char-mime.rhtml
にも書かれているように、単独では使われない符号化文字集合です。

>ADODB.Stream では、既定値の "Unicode" のままにしておけば、
U+FF00〜U+FFEF の "Halfwidth and Fullwidth Forms(半角・全角形)" の
カテゴリに所属する文字として入出力されると思います。

>なお、「シフトJIS」を指定する場合には、Charasetプロパティに
"csWindows31J"
"csShiftJIS"
"Shift_JIS"
"shift-jis"
"x-ms-cp932"
"x-sjis"
のいずれかを指定すればOKです。

#参考リンク
[コードページリスト Pentan.com](https://pentan.info/doc/codepage_list.html)
ただし、1201をUTF-16BEとしているのは誤りだと考えられる。BEならUnicodeFEFFという名前になる。
1201はBOMがつく、UTF-16でかつ並び順がリトルエンディアンであり1200がUTF-16LEである。
そして1200がWindowsのUNICODEということになる。
[漢字コード - 文字コード](http://www.tohoho-web.com/ex/draft/kanji.htm)
UTF-16LEとUTF-16BEそしてUTF-16(BOMあり)のLEとBEと4つを区別して記載している例。

[UCSとUTF 2003](http://nomenclator.la.coocan.jp/unicode/ucs_utf.htm)
[VBA : ADODB.Stream 以下のヘルプの内容を一覧にまとめたもの](http://blogwizhook.blog.fc2.com/blog-entry-217.html)
[Open メソッド (ADO Stream) ](https://docs.microsoft.com/ja-jp/office/client-developer/access/desktop-database-reference/open-method-ado-stream)
[Read メソッド(ADO)](https://docs.microsoft.com/ja-jp/office/client-developer/access/desktop-database-reference/read-method-ado)
[ReadText メソッド(ADO)](https://docs.microsoft.com/ja-jp/office/client-developer/access/desktop-database-reference/readtext-method-ado)
[Write メソッド (ADO)](https://docs.microsoft.com/ja-jp/office/client-developer/access/desktop-database-reference/write-method-ado)
[WriteText メソッド (ADO)](https://docs.microsoft.com/ja-jp/office/client-developer/access/desktop-database-reference/writetext-method-ado)
[StreamOpenOptionsEnum](https://docs.microsoft.com/ja-jp/office/client-developer/access/desktop-database-reference/streamopenoptionsenum)
[StreamReadEnum](https://docs.microsoft.com/ja-jp/office/client-developer/access/desktop-database-reference/streamreadenum)
[StreamTypeEnum](https://docs.microsoft.com/ja-jp/office/client-developer/access/desktop-database-reference/streamtypeenum)
[StreamWriteEnum](https://docs.microsoft.com/ja-jp/office/client-developer/access/desktop-database-reference/streamwriteenum)