2

Windows Scripting Host から既存のXLS ファイルの内容をすばやく操作する方法はありますか?

顧客から受け取った Excel テンプレートがあります。私たちの仕事は、これらのテンプレートに Oracle データベースから取得したデータを入力することです。

現在のアプローチは、Windows Scripting Host と VBScript を使用することです。

  1. ADODB を使用して Oracle からデータを取得します。

    Set db = CreateObject("ADODB.Connection")
    SQL = "SELECT ..."
    Set rs=db.execute(SQL)
    
  2. VBScript を使用して、Windows Scripting Host で Excel オブジェクトを作成します。

    Set objExcel = CreateObject("Excel.Application")  
    Set objWorkbook = objExcel.Workbooks.Open(xls_final)  
    Set objSheet = objWorkBook.Sheets(1)
    
  3. そして、次のようにテンプレートのセルごとに入力します。

    If rs.EOF = False Then
       rs.MoveFirst
       Do Until rs.EOF
          objSheet.Cells(RowNumber, 1).Value = rs("COLUMN1")
          objSheet.Cells(RowNumber, 2).Value = rs("COLUMN2")
          objSheet.Cells(RowNumber, 3).Value = rs("COLUMN3")
          rs.MoveNext
       Loop
    End If
    objWorkbook.Save 
    rs.Close
    

問題は、これらのファイルの一部に大量のデータが含まれており、このように埋めるのに何時間もかかることです。それを行うより速い方法はありますか?

4

4 に答える 4

6

ここまでは大丈夫だと思います:

Set db = CreateObject("ADODB.Connection")
SQL = "SELECT ..."
Set rs=db.execute(SQL)

Set objExcel = CreateObject("Excel.Application")  
Set objWorkbook = objExcel.Workbooks.Open(xls_final)  
Set objSheet = objWorkBook.Sheets(1)

しかし、あなたが発見したように、残りは恐ろしく遅くなるでしょう。ワークシートとのやり取りには高いオーバーヘッドがあり、すべての行のすべての列に対して支払う必要があります。これにはいくつかの方法があります。

最も簡単なのは

objSheet.Cells(1,1).CopyFromRecordset rs

最初に試すことをお勧めします。

于 2009-04-20T08:09:09.480 に答える
2

これを見てください。
http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=49926
Excel を操作するのではなく、ADODB を使用して Excel に接続する場合にも役立ちます。ヘルプが必要な場合は、この記事をお読みください。
http://support.microsoft.com/kb/257819

于 2009-04-20T17:34:53.847 に答える
1

1 つの可能性は、2 段階のプロセスにすることですが、ボトルネックがどこにあるかによって異なります。

Excel の場合は、レコードセットの行を CSV タイプのファイルに変換し、それが完了したら Excel オブジェクトを作成し、ファイル全体を固定の場所にインポートします。

これはおそらく、セルごとの操作よりも高速になるでしょう。

シートの固定位置に CSV をインポートできない場合 (セルが連続した行または列にない場合)、CSV を新しいシートにインポートし、そこからテンプレート シートに一括コピーします。

範囲の移動も、セルごとの操作よりも高速である必要があります。

いくつかの良い改善をもたらすのは、一括インポートと一括コピーです。より複雑な Excel 機能を使用すると、個々のセルを処理するワークシートが 10 倍も速くなりました (VBA で個々のセルを合計してその値をどこかに置くのではなく、=sum(a1..a999) を使用することを考えてください)。 )。

VBA からインポートする方法については、私は常にこの"Record Macro"機能を利用して、変更可能なベースラインを取得しています (よく知らない人向け)。c:\x.csvこれは の現在のシートにインポートされC7ます:

With ActiveSheet.QueryTables.Add(Connection:="TEXT;C:\x.csv", _
    Destination:= Range("C7"))
    .Name = "x"
    .FieldNames = True
    .RowNumbers = False
    .FillAdjacentFormulas = False
    .PreserveFormatting = True
    .RefreshOnFileOpen = False
    .RefreshStyle = xlInsertDeleteCells
    .SavePassword = False
    .SaveData = True
    .AdjustColumnWidth = True
    .RefreshPeriod = 0
    .TextFilePromptOnRefresh = False
    .TextFilePlatform = 850
    .TextFileStartRow = 1
    .TextFileParseType = xlDelimited
    .TextFileTextQualifier = xlTextQualifierDoubleQuote
    .TextFileConsecutiveDelimiter = False
    .TextFileTabDelimiter = True
    .TextFileSemicolonDelimiter = False
    .TextFileCommaDelimiter = True
    .TextFileSpaceDelimiter = False
    .TextFileColumnDataTypes = Array(1, 1, 1)
    .TextFileTrailingMinusNumbers = True
    .Refresh BackgroundQuery:=False
End With

そこにあるゴミのほとんどは削除できると確信していますが、問題が発生しないように、一度に1つずつ削除することをお勧めします.

次のように変更して、別のシートを使用することもできます。

dim ws as worksheet
dim savealert as boolean
set ws = Sheets.Add
ws.select
' Put all that other code above in here. '
' Move all that data just loaded into a real sheet. '
savealert = Application.DisplayAlerts
Application.DisplayAlerts = False
ws.delete
Application.DisplayAlerts = savealert
于 2009-04-20T05:22:22.080 に答える
0

OLEDB 接続を介してアクセスでき、無限に高速です。

スプレッドシートからデータベースにデータをインポートするために使用するスクリプトのコードを次に示します。明らかに、カーソルのタイプとロックのタイプを変更したいでしょうが、アイデアは得られます。

strExcelConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & objFile.Path & ";Extended Properties=""Excel 8.0;HDR=Yes"""
strSQL = "SELECT * FROM [RegistrationList$] ORDER BY DateToRegister DESC"

objExcel.Open strSQL, strExcelConn, adOpenForwardOnly, adLockReadOnly, adCmdText
于 2009-04-22T22:04:41.937 に答える