要約
CSV出力時に全角文字でエラー
原因は、FileSystemObjectのANSI書き込みでした。
ANSIは、Windowsのローカルコードページのため、
環境によってANSIが異なります。
そのためUnicode→ANSI変換ができないことが問題になってました。
はじめに
自己の立場を軽く。
新卒から2年目までWEB系のバック、フロントエンドをRubyで経験。
4年異業種を経験し、再度IT職のSESへ転職しました。
そこでVue、REACTなどモダンな言語を数カ月経験した後に、
現在のASPclassicにアサインという流れになります。
背景
ASP Classic / VBScript の既存システムを、
海外向け環境へのリプレイス作業をしていた際に、
CSV出力のエラーに出くわしました。
データベースの Recordset を CSV 出力する処理でのエラーになります。
半角英数字だけなら問題ないですが、
日本語(全角文字)が含まれるとエラーになるという内容です。
発生したエラー
CSVを書き出す処理で次のエラーが発生しました。
Microsoft VBScript runtime error '800a0005'
Invalid procedure call or argument
該当コード
' サンプルコード
' Recordset を CSV 文字列に変換
csvText = rs.GetString(2, , ",", vbCrLf, "")
' ファイル書き込み
Set fso = CreateObject("Scripting.FileSystemObject")
Set file = fso.CreateTextFile("output.csv", True)
file.Write csvText
file.Close
処理内容
- Recordset を CSV 文字列に変換
- ファイル作成、書き込み
| データ | 文字 | Center align |
|---|---|---|
| ABC123 | 半角英数字 | ◯ |
| 東京 | 日本語 | ✕ |
つまり、半角英数字はOK、日本語はNGでした。
CreateTextFileが原因
GetString は Recordset を文字列化するだけなので、
エラーは CSV 書き込み側にあるという結論になります。
そのため、FileSystemObject の文字コードの変換・仕様が原因になります。
Unicode → ANSI変換の際、
海外のANSIへの日本語対応ができないことが原因でした。
そもそもANSIとは
文字コードの調査過程で、ANSIという言葉がよくできました。
ただここで疑問:ANSIって何?
ANSI = 環境依存の文字コード(環境依存の文字)
| 環境 | ANSIコード |
|---|---|
| 日本 | Shift-JIS |
| 英語圏 | Windows-1252 |
つまり、
Unicode → ANSI変換の際に
存在しない文字となり、結果としてエラーになりました。
じゃあなぜ半角英数字は通るのか?
半角英数字はASCII文字のため、
Unicode → ANSI変換でも問題なく通ります。
ASCIIは基本128文字 を定義した文字コードであり、
すべてのANSIの共通部分になってるため変換でも問題なく通るのです。
Shif-JISだから通らないのか?
自身もレコード内容がShift-JISだから通らないと思っていましたが、
正確には、DB→Unicode→ANSIでの変換が肝になってます。
VB Sctriptでは、内部文字は基本的にUnicodeとして扱われます。
つまり
Recordset
↓
GetString
↓
Unicode文字列
Unicode → ANSI
ANSI = Shift-JIS (日本環境)
Unicode → Shift-JIS
この場合、「山田」入力だと存在する
ANSI = Windows-1258(英語環境)
この場合、「山田」入力だと存在しない
つまり日本環境なら問題ないが、
英語圏だとUnicodeからの変換ができないです。
解決方法
文字コードを UTF-8 で書き出すようにします。
ASP Classic でADODB.Stream を使う方法
Set stream = CreateObject("ADODB.Stream")
stream.Type = 2
stream.Charset = "UTF-8"
stream.Open
stream.WriteText csvText
stream.SaveToFile "output.csv", 2
stream.Close
これにより、Unicode → UTF-8として保存されるため
日本語、英語、その他言語において安全に扱えます。
まとめ
CSV出力時に全角文字でエラー
原因は、FileSystemObjectのANSI書き込みでした。
ANSIは、Windowsのローカルコードページのため、
環境によってANSIが異なります。
そのためUnicode→ANSI変換ができないことが問題になってました。
補足
GetStringで調べた内容になります。
Recordset.GetString(StringFormat, NumRows, ColumnDelimiter, RowDelimiter, NullExpr)
| 引数 | 文 | 内容 |
|---|---|---|
| StringFormat | 2 | 文字列形式で出力 |
| NumRows | 省略(取得行数) | 今回は全レコード |
| ColumnDelimiter | "," | カンマ区切り |
| RowDelimiter | vbCrLf | 改行 |
| NullExpr | "" | 空文字 |