Tips【VBA】ADODBを使ってメモリtoメモリで文字コード変換を行う(ファイルに書かない)
VBAを使ってWEBのデータを取り込んでEXCELに貼り付けようといったときに、文字コードの変換の必要があります。
UTF-8とか、Shift-JISとかで取り出した(帰ってきた)データをVBAの文字列(UNICODE)に変換する方法の覚え書き
ADODB.Streamをつかう
マニュアルはここらへんかな?
Stream オブジェクト (ADO) | Microsoft Docs
WebでADODB.Streamで文字コード変換を検索しても、ファイルに書き込むとかファイルから読み込むとかばかりでなかなか見つからない。
肝心のマニュアルもサンプルとか全然ないのでいまいち。
今回やりたいのはメモリtoメモリなのでファイル名とかURLとか指定せずにStreamで完結させる。
ストリームでオープンしてバイナリモードで書き込んで、テキストモードで読み込めばいいじゃん
ということでこんな感じで関数
ソース
' ' 文字コード変換を行い文字列(UNICODE)にする ' 引数 bin 元のバイナリデータ(変換前) ' encoding 元の文字コード(UTF-8、Shift-JIS etc) ' Public Function GetString(ByRef bin, ByVal encoding As String) As String Const adTypeBinary = 1 Const adTypeText = 2 With CreateObject("ADODB.Stream") .Open .Type = adTypeBinary .Write bin .Position = 0 .Type = adTypeText .Charset = encoding GetString = .ReadText .Close End With End Function
説明
オープンして、バイナリで書き込んで、ポインタを先頭(0)にして、テキストモードで(エンコーディング指定して)読み込む
ってそのまんまやん
さて、性能は?
CreateObjectしたり、Open/Closeしたり(ファイルとかに書き込んでないはずだけど)オーバーヘッドが気になります。
性能測定
こんな感じで時間計測処理を組み込みます。
変数aに適当なUTF-8とかの文字列を入れて
startTimer = Timer a = GetString(a, "utf_8") Debug.Print Len(a) Debug.Print "time=" & (Timer - startTimer)
30620 time=0.0078125 30620 time=0.0390625 30620 time=0.0078125
30Kbyteくらいの文字列の変換が数ms~数十ms
ちなみに長さを表示しているDebug.Print Len(a)をコメントアウトすると
time=0 time=0 time=0 time=0.0234375 time=0 time=0.015625 time=0 time=0 time=0.0234375 time=0
ほとんど影響ないくらいの時間ですね。
この関数をループの中から大量に呼び出すとかはあまり考えられないので、毎回CreateObjectしてもあまり問題なさそうですし。
Charsetってどんなのが設定できるの?
代表的なものは以下くらいでしょうか
utf-8、shift_jis、euc-jp、iso-2022-jp、unicode
※最近だとeucとかiso-2022-jpの文字コードのページはほとんど見かけませんねぇ