2015年08月21日 Sort in VBScript with ADODB [長年日記]
_ Sort in VBScript with ADODB
adodb.recordsetのsortメソッドは以下に示すように、ロケール指定無しの「sort」コマンドと同様に機能する。
C:\Users\m-ito>type testdata.txt あ ←ここは全角スペース 12 C:\Users\m-ito>sort testdata.txt ←ここは全角スペース 12 あ C:\Users\m-ito>sort /L C testdata.txt 12 ←ここは全角スペース あ C:\Users\m-ito>type sorttest.vbs Option Explicit Dim objRs Set objRs = CreateObject("ADODB.Recordset") objRs.Fields.Append "key1", 200, 256 objRs.Open While Not WScript.StdIn.AtEndOfStream objRs.AddNew objRs.Fields("key1").Value = WScript.StdIn.ReadLine Wend objRs.Sort = "key1 ASC" objRs.MoveFirst While Not objRs.EOF WScript.StdOut.WriteLine objRs.Fields("key1").Value objRs.MoveNext Wend C:\Users\m-ito>cscript /nologo sorttest.vbs <testdata.txt ←ここは全角スペース 12 あ C:\Users\m-ito>
ところが、VBScript中の大小判定(">", "<")は「sort /L C」コマンドの並び順と一致する。UNIX系OSで言うと「LC_ALL=C sort」と同じ意味なので、単純に文字コードの並びとなる。
この状態だと、VBScriptで並び替えたデータを大小判定を伴う別のVBScriptで処理すると矛盾を生じる場合がある。
なので、「sort /L C」コマンドと同じ並びを実現しようとするのだが、「SetLocale(lcid)」関数では「C」ロケールを意味する引数が存在しない(?)。
そこで、無理矢理ねじ込んだのが以下の方法。
C:\Users\m-ito>sort /L C testdata.txt 12 ←ここは全角スペース あ C:\Users\m-ito>type sorttest.vbs Option Explicit ' ' 文字列を文字コードの16進数文字列に変換する ' Function getHexString(str) Dim strChar Dim strHex Dim intLen Dim intCnt strHex = "" intLen = Len(str) For intCnt = 1 To intLen strChar = Mid(str, intCnt, 1) strHex = strHex & Hex(Asc(strChar)) Next getHexString = strHex End Function ' ' 主処理 ' Dim strRec Dim objRs Set objRs = CreateObject("ADODB.Recordset") objRs.Fields.Append "key1", 200, 256 objRs.Fields.Append "data", 200, 256 objRs.Open While Not WScript.StdIn.AtEndOfStream objRs.AddNew strRec = WScript.StdIn.ReadLine objRs.Fields("key1").Value = getHexString(strRec) objRs.Fields("data").Value = strRec Wend objRs.Sort = "key1 ASC" objRs.MoveFirst While Not objRs.EOF WScript.StdOut.WriteLine objRs.Fields("data").Value objRs.MoveNext Wend C:\Users\m-ito>cscript sorttest.vbs <testdata.txt 12 ←ここは全角スペース あ C:\Users\m-ito>
簡単に説明すると、ソートキーの対象を「生」の文字列とせずに、文字コードを16進数表現の文字列に変換したものをソートキーの対象として設定すると、期待したとおりの並びとなる。