Groovyでテーブルのデータを取得したい(5)

先日の日記で、SafeArrayを使用してスクリプトの時間短縮にチャレンジしたのですが、
まだまだ時間がかかるため、もっと改良できないかと思案中。。。


ただ、SafeArrayのコンストラクタには2次元以上の配列を受け取るものが存在しないので
無理なのかと思っていたのですが、putAtというメソッドを発見しました。
http://groovy.codehaus.org/modules/scriptom/1.6.0/scriptom/apidocs/org/codehaus/groovy/scriptom/SafeArray.html

第一引数、第二引数ともにObject型をとりますが、第一引数には行列を表すリストを指定できます。(←いろいろ試してみた結果)
第二引数には、設定したい値を指定します。
putAtで行列データを挿入していくためには、コンストラクタで行列数をRange(1..N)指定してやる必要があるようです。(←いろいろ試してみた結果)


SafeArray safeArray = new SafeArray(型の種類,1..行数,1..列数)


これで行数分(約4万回)worksheet.rangeをコールしていた部分が、一気にテーブル分(19回)に減ります。
改良したコードは以下の通りです。

import java.text.SimpleDateFormat
import org.codehaus.groovy.scriptom.ActiveXObject
import org.codehaus.groovy.scriptom.SafeArray
def sql = groovy.sql.Sql.newInstance('jdbc:oracle:thin:@localhost:1521:ORCL','userid','password','oracle.jdbc.driver.OracleDriver')
def xlApp = new ActiveXObject('Excel.Application')
def username = "INIT"
def workbook = xlApp.workbooks.Add
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss")
sql.eachRow("SELECT table_name FROM user_tables WHERE table_name LIKE 'BIZ_AB_%'"){ rs->
    def rows = sql.rows("SELECT * FROM " + rs.table_name +" WHERE create_user_cd ='" + username + "'")
    if( rows.size() > 0 ){
        def worksheet = workbook.worksheets.Add
        worksheet.name = rs.table_name
        def (long rowNumber, long colNumber) = [1,1]
        SafeArray safeArray = new SafeArray(org.codehaus.groovy.scriptom.SafeArray.VARIANT,1..rows.size()+1,1..rows[0].size())
        for(r in rows){
            if(1==rowNumber){
                r.each{ safeArray.putAt([rowNumber,colNumber++],it.key) }
                rowNumber++
            }
            colNumber = 1
            r.each{
                if( it.value instanceof oracle.sql.TIMESTAMP )
                    it.value = sdf.format(it.value.dateValue())
                safeArray.putAt([rowNumber,colNumber++],it.value)
            }
            rowNumber++
        }
        worksheet.Range(worksheet.cells(1,1),worksheet.cells(rows.size()+1,rows[0].size())).Value = safeArray
    }
}
xlApp.visible = true


これで約19秒で実行できるようになりました。(140秒→19秒)
もっと劇的に早くできる方法はないか、模索中です。