[VBScript]コード内でUNICODE文字を扱う場合及びCMDでユニコード文字の番号を知る方法

#VBScript自体はANSI(shift-jis）かUTF-16LE
スクリプト自体はANSI Or UTF-16LEでしか使えない。
UTF-8の`.vbs`は動かない。
このためNotepadでVBScriptを新規作成するときは
`NotePad /a "C:\hogehoge\NewVbs.vbs`
というように`/a`オプションででANSIにする。
しかしこの場合&#9829;&#12850;&#232;&#233;&#234;&#235;.txtのようなファイル名があるとANSIで保存できない。
こういう場合には`ChrW(&H2665) & ChrW(&H3232) & ChrW(&HE8) & ChrW(&HE9) & ChrW(&HEA) & ".txt"`と表記する。
しかし、このような番号をどうやって取得すれば良いか。Excelを使う方法はすでに扱っているが、Excelがない場合どうするか。

# ChrWとAscWの使い分け
ANSIでUnicode文字を扱うポイントは＆Hの16進表示でChrWを使う `ChrW(&H3232)`。
これによって、ANSIでは表記されない文字を表記できる。可読性はないが、VBSCRIPTやVBAでユニコード文字を扱うには、このような方法しかない。
`ChrW(&H3232) & "架空のITサービス`
とすると&#12850;架空のITサービスとなる

```vb:VBScript
' ChrWTest.vbs
Wscript.Echo ChrW(&H3232) '有限会社の（有）
Wscript.Echo AscW(ChrW(&H3232)) '12850 十進
Wscript.Echo Hex(Asc(ChrW(&H3232))) '3232 '16進
Wscript.Echo "&H" & Hex(Asc(ChrW(&H3232))) '&H3232 16進 はHexだけでなく "&H" & HEX() とすること
Wscript.Echo "&#" & Asc(ChrW(&H3232)) & ";" 'Webページでは &H#XXXXX;とすると、機種依存文字が表示される（例外あり）
```

#CMD+CSCRIPTから文字コードを知る方法UTF-8出力
CMDを起動する
chcp 65001
と入力してUTF-8で出力されるようにする。

`Cscript //Nologo UnicodeNumberCScipt.vbs `"&#9829;&#12850;"`>C:\hoge\rstUtf8.txt`
Qiitaの表記上このようにコマンドラインで引数にする。（※Qiitaの現在のマークダウンは\`\`で囲むと意図した文字&#9829;ではなく`&#9829;`十進ユニコード番号表記になるため、囲みを外しています
#CMD+CSCRIPTから文字コードを知る方法UTF-16LE出力（ただし当方の環境ではエラー）
`CMD /u`として起動する
`Cscript //Nologo UnicodeNumberCScipt.vbs `"&#9829;&#12850;"`>C:\hoge\rstUtf16.txt`
これでできたファイルはNOTEPADでは半角の英数字が全角になるなどの文字化けする。SAKURAエディタでは読める。


###特殊文字の早見表
その他よく使うものがこちら
https://sakichin.com/other/html_words.html
###CMDで出力される十進数とWebページは正の場合は一致している
しかし、この上記のページをみると、&\#十進数字というコードだけで結構な記号を表すことができることがわかる。しかもその番号はこの方法によって得ることができる。
###全部を表記することはできない。
以下のスクリプトは、単純に`&#`をつけている。しかし、半角スペース、円マーク、タブ記号などは&\#表記ではないので、この方法ですべての特殊文字が表示できるわけではない。
&#9829;&#12850;&#232;&#233;&#234;&#235;ｱｲｳｴｵ&#4325;&#4304;&#4320;&#4311;&#4323;&#4314;&#4312;
の中身をスクリプトで取得すると、　
`&#9829;&#12850;&#232;&#233;&#234;&#235;&#-143;&#-142;&#-141;&#-140;&#-139;&#4325;&#4304;&#4320;&#4311;&#4323;&#4314;&#4312;`
と、いちおう取得できる。
こうなる。しかし、実際にマイナスになる番号をそのまま使うとうまくいかない。
このようになってしまう。
&#9829;&#12850;&#232;&#233;&#234;&#235;&#-143;&#-142;&#-141;&#-140;&#-139;&#4304;&#4320;&#4311;&#4323;&#4314;&#4312;
ქართული
####どうしても出したいときはマイナスの場合は65536を加算する
[半角カナの数値文字参照](http://webnote.motq.net/html/sum/hankaku.htm)
&#9829;&#12850;&#232;&#233;&#234;&#235;&#65393;&#65394;&#65395;&#65396;&#65397;&#4325;&#4304;&#4320;&#4311;&#4323;&#4314;&#4312;
マイナスの場合は65536[DEC]を加算する。
`&#9829;&#12850;&#232;&#233;&#234;&#235;&#65393;&#65394;&#65395;&#65396;&#65397;&#4325;&#4304;&#4320;&#4311;&#4323;&#4314;&#4312;`

$-143+65536=65393$

###CScriptで指定された文字のユニコードをダンプ出力するVBScript

```vb:VBScript
Dim var
Dim i
Dim str
Dim cnt
If Wscript.Arguments.count>0 then
Set var = Wscript.Arguments
'Wscript.Echo TypeName(var(0))
Wscript.Echo "番号" & vbTab &  "ユニコード文字" & vbTab & "ユニコード文字番号"
IF Typename(var(0)) = "String" Then
str = cStr(var(0))
for i = 1 to Len(str)
' どちらか一つを使用する
WScript.Echo i & vbTab & MID(str,i,1) & vbTab & "&H" & HEX(AscW(MID(str,i,1)))
' Webページ用
WScript.Echo i & vbTab & MID(str,i,1) & vbTab & "&#" & AscW(MID(str,i,1)) & ";" ' Webページ用
' Webページ用はマイナスになるとエラーになるため、マイナスの場合は65536を足す。半角カタカナで発生する。
'  IF AscW(MID(str,i,1)) <> -1 Then
'  .WriteText  i & vbTab & MID(str,i,1) & vbTab & "&H" & HEX(AscW(MID(str,i,1))) & vbTab & "&#" & AscW(MID(str,i,1)) & ";",1
'  Else
'  .WriteText  i & vbTab & MID(str,i,1) & vbTab & "&H" & HEX(AscW(MID(str,i,1))) & vbTab & "&#" & AscW(MID(str,i,1))+65536 & ";",1
'  End IF
WScript 
Next
End If
End If
```

####しかし番号は取得できるが文字化けする時がある

このとき932にしたままだと出力したダンプファイルは
`1	?	&#9829;`
となる
chcp 65001に変更すると
`1	?	&#9829;`
やっぱりこうなる。

###VBSCRIPTで文字コードをUTF-16LEで出力
`Cmd /a`で起動する。
Currentを`C:\hoge\`
そこにあると仮定している`CscriptUnicodeNumberUTF16LE.vbs`を使う
`Cscript //Nologo CscriptUnicodeNumberUTF16LE.vbs `"&#9829;&#12850;"
のようにCscriptを用いて、引数に求めるユニコード文字列を書く。文字列はダブルクォーテーションで囲む。
UnicodeNumberUTF16LE.txtに出力する。既存のファイルは削除する。
（おそらく番号を知れば十分というのが一般的であろうと判断してこういう仕様にしています、これを回避したいときは確認メッセージをだすかユニークなファイル名にしてください）
CHCPを使わず、FSOでUTF-16LEに出力します。（改行はvbCrLf)


```vb:VBScript
Const ForReading = 1 'AS Long
Const ForWriting = 2 'AS Long
Const ForAppending = 8 'AS Long
Const WindowsFolder = 0 'AS Long
Const TemporaryFolder = 2 'AS Long
Const UTF16True = -1 'As Boolean vbTrue
Const vTristateFalse = 0
Const vTristateTrue =-1
Const vTristateMixed =-2
Const vTristateUseDefault =-2
Const adModeReadWrite = 3
Const adTypeBinary = 1
Const adTypeText = 2
Const adSaveCreateOverWrite = 2

Dim var
Dim i
Dim str
Dim cnt
Dim FSO : Set fso = createObject("Scripting.FileSystemObject")
Dim TS
Dim strListFileFullName
If Wscript.Arguments.count>0 then
Set var = Wscript.Arguments

'Wscript.Echo TypeName(var(0))
IF Typename(var(0)) = "String" Then
strListFileFullName = fso.getParentFolderName(WScript.ScriptFullName) & "\UnicodeNumberUTF16LE.txt"
IF fso.fileExists(strListFileFullName) Then fso.DeleteFile(strListFileFullName)
Set TS = Fso.OpenTextFile(fso.getParentFolderName(WScript.ScriptFullName) & "\UnicodeNumberUTF16LE.txt" , ForWriting, True, vTristateTrue) 'テキストストリーム作成（リストファイル生成,UTF-16LE BOMはUTF-16LEの定義上付与されない) 
Ts.WriteLine "番号" & vbTab &  "文字" & vbTab & "文字番号" & VbTab & "HTMLのコード"
str = cStr(var(0))
for i = 1 to Len(str)
Ts.WriteLine i & vbTab & MID(str,i,1) & vbTab & "&H" & HEX(AscW(MID(str,i,1))) & vbTab & "&#" & AscW(MID(str,i,1)) & ";"
Next
Ts.Close
End If
End If
```

##UTF-16LEとUTF-8BOMとUTF-8Nで出力
このときはchcp 932で起動します。`CMD`でもいいし、`CMD /a`でも良いです。タスクバーにアドレス欄を儲けておきましょう。
起動後VBSCRIPTのあるフォルダに`CD /D C:\hoge`のように移動して
`Cscript //Nologo CscriptOUtputUnicodeNumber168B8N.VBS `"&#9829;&#12850;&#232;&#233;&#234;&#235;ｱｲｳｴｵ;&#4304;&#4320;&#4311;&#4323;&#4314;&#4312;"


```vb:VBScript
' File Name CscriptOUtputUnicodeNumber168B8N.VBS
' How To Use
' [Win]+R
' CMD /a
' CD /D 'parentfolder
' Cscript //Nologo CscriptOUtputUnicodeNumber168B8N.VBS "UNICODECHARACTER"
Const ForReading = 1 'AS Long
Const ForWriting = 2 'AS Long
Const ForAppending = 8 'AS Long
Const WindowsFolder = 0 'AS Long
Const TemporaryFolder = 2 'AS Long
Const UTF16True = -1 'As Boolean vbTrue
Const vTristateFalse = 0
Const vTristateTrue =-1
Const vTristateMixed =-2
Const vTristateUseDefault =-2
Const adModeReadWrite = 3
Const adTypeBinary = 1
Const adTypeText = 2
Const adSaveCreateOverWrite = 2

Dim var
Dim i
Dim str
Dim cnt
Dim FSO : Set fso = createObject("Scripting.FileSystemObject")
Dim TS
Dim strListFileFullName
If Wscript.Arguments.count>0 then
Set var = Wscript.Arguments

'Wscript.Echo TypeName(var(0))
IF Typename(var(0)) = "String" Then
strListFileFullName = fso.getParentFolderName(WScript.ScriptFullName) & "\UnicodeNumberUTF16LE.txt"
IF fso.fileExists(strListFileFullName) Then fso.DeleteFile(strListFileFullName)
Set TS = Fso.OpenTextFile(fso.getParentFolderName(WScript.ScriptFullName) & "\UnicodeNumberUTF16LE.txt" , ForWriting, True, vTristateTrue) 'テキストストリーム作成（リストファイル生成,UTF-16LE BOMはUTF-16LEの定義上付与されない) 
Ts.WriteLine "番号" & vbTab &  "ユニコード文字" & vbTab & "ユニコード文字番号"
str = cStr(var(0))
for i = 1 to Len(str)
Ts.WriteLine i & vbTab & MID(str,i,1) & vbTab & "&H" & HEX(AscW(MID(str,i,1)))
  IF  Sgn(AscW(MID(str,i,1)) ) <> -1 Then
  Ts.WriteLine i & vbTab & MID(str,i,1) & vbTab & "&#" & AscW(MID(str,i,1)) & ";" ' Webページ用
  Else
  Ts.WriteLine i & vbTab & MID(str,i,1) & vbTab & "&#" & AscW(MID(str,i,1))+65536 & ";" ' Webページ用
  End If
Next
Ts.Close
End If
End If

Dim sr, strTempFileName
Dim iStr
Dim oStr

IF Typename(var(0)) = "String" Then
Set sr = CreateObject("ADODB.Stream")
Set oSr = CreateObject("ADODB.Stream")
strListFileFullName =""
strListFileFullName = fso.getParentFolderName(WScript.ScriptFullName) & "\UnicodeNumberUTF8.txt"
strTempFileName =  fso.getParentFolderName(WScript.ScriptFullName) & "\UnicodeNumberUTF8N.txt"
IF fso.fileExists(strListFileFullName) Then fso.DeleteFile(strListFileFullName)
IF fso.fileExists(strTempFileName) Then fso.DeleteFile(strTempFileName)
With sr
.Mode = adModeReadWrite
.Charset = "UTF-8"
.Type = adTypeText
.Open
.WriteText  "番号" & vbTab &  "文字" & vbTab & "文字番号" & VbTab & "HTMLのコード",1
for i = 1 to Len(str)
' Web用はマイナスの場合65536を加算
  IF AscW(MID(str,i,1)) <> -1 Then
  .WriteText  i & vbTab & MID(str,i,1) & vbTab & "&H" & HEX(AscW(MID(str,i,1))) & vbTab & "&#" & AscW(MID(str,i,1)) & ";",1
  Else
  .WriteText  i & vbTab & MID(str,i,1) & vbTab & "&H" & HEX(AscW(MID(str,i,1))) & vbTab & "&#" & AscW(MID(str,i,1))+65536 & ";",1
  End IF
Next
.SaveToFile strListFileFullName, 2 'ここがポイント、保存してもCloseさせずそのままBOMを削除に移行
End With
' Binaryを開く
With oSr
  .Mode = adModeReadWrite
  .Type = adTypeBinary
  .Open

'ここでsrを開いたままでポジションを0にする。そのあと、バイナリモードにスィッチして、ポジションを3にする。これでBOMをスキップ
  With sr
   .Position = 0 
   .Type = adTypeBinary
   .Position = 3
  End With
  ' write remaining bytes to file and clean up
  .Write Sr.Read
  .SaveToFile strTempFileName, adSaveCreateOverWrite
  .Close
  Sr.Close
End With
End IF
Set sr = Nothing
Set oSr = Nothing
```

このような場合にVisualBasic、C#を使う例はあったが、VBSCriptで対応可能である。

##Powershell、CMDの画面ではMSゴシックはグルジア文字やアラビア文字が表示されない
Powershell,CMDとも共通しているが、それぞれのコンソールでMSゴシックを設定するとUNicodeもかなり表示できる。しかしグルジア文字はアラビア文字は文字化けする。
しかし、メモ帳をMS UI ゴシックにして、上記のVBScriptで出力すると、表示される。
UTF-8だと半角カナも文字化けするか、とにかくすべての言語を表示させることは難しい。
またUTF-16LEもCMD /Uでやるとメモ帳ではうまく開けない。しかしVBSだとうまくいく。

このため、文字のユニコードを調べたいときは
cmdを起動してchcp 932(標準）の状態で、上記の手順でvbsを使う。という方法で文字に対応するユニコード番号を取得できる。
Webページは`&#'をつける。このため、上記のスクリプトでは`&#'つきで十進表示し、マイナスの場合は失敗するので65532を加算して表示している。
通常のVBSやVBAの場合は`ChrW(&H)`を使う。このため上記のスクリプトはすでに＆Hをつけて表示している。