トップ «前の日記(2015年07月12日) 最新 次の日記(2015年08月27日)» 編集

Masa's blog

検索キーワード:

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進数表現の文字列に変換したものをソートキーの対象として設定すると、期待したとおりの並びとなる。