2

OK、かなり大量のレコード (~3500) を生成するスプレッドシートがあります。

それらをアクセスデータベースに挿入する次のスクリプトがあります。

Sub putinDB()
Dim Cn As ADODB.Connection, Rs As ADODB.Recordset
Dim MyConn, sSQL As String

Dim Rw As Long, c As Long
Dim MyField, Result
Dim x As Integer
Dim accName As String, AccNum As String, sector As String, holding As String,  holdingvalue As Double, holdingdate As Date
theend = lastRow("Holdings", 1) - 1
'Set source
MyConn = "S:\Docs\Harry\Engine Client\Engine3.accdb"
'Create query
Set r = Sheets("Holdings").Range("a2")
x = 0
Do
Application.StatusBar = "Inserting record " & x + 1 & " of " & theend
accName = r.Offset(x, 0)
AccNum = r.Offset(x, 4)
sector = r.Offset(x, 2)
holding = r.Offset(x, 1)
holdingvalue = r.Offset(x, 3)
holdingdate = r.Offset(x, 5)

sSQL = "INSERT INTO Holdings (AccName, AccNum, Sector, Holding, HoldingValue, HoldingDate)"
sSQL = sSQL & " VALUES ('" & Replace(accName, "'", "''") & "', '" & AccNum & "', '" & sector & "', '" & Replace(holding, "'", "''") & "', '" & holdingvalue & "', #" & holdingdate & "#)"
Debug.Print (sSQL)
 'Create RecordSet
Set Cn = New ADODB.Connection
With Cn
    .Provider = "Microsoft.ACE.OLEDB.12.0"
    .CursorLocation = adUseClient
    .Open MyConn
    Set Rs = .Execute(sSQL)
End With
x = x + 1
Loop While r.Offset(x, 0) <> "" Or x < 15
Application.StatusBar = False
End Sub

問題は、各レコードを1つずつループし、毎回クエリを再構築して実行するため、実行が非常に遅くなることです(私のPCでは毎秒約2〜3レコード)

ループすることなく、vba で範囲全体を一度に DB に挿入する方法はありますか? ありがとう

4

2 に答える 2

7

あなたが提供した答えは、接続を開く必要があるのは1回だけなので、状況はわずかに改善されるはずですが、コードはまだ非効率的です. このようにするのではなく、すべてのデータを一度だけレコードセットに書き込みたいのです。私は常に、Excel から Access にプッシュするよりも、Access 側で作業して Excel から情報を取得することを好みますが、このシナリオではどちらも使用できると思います。

この場合、ADO よりも DAO を使用してTransacationを操作する方が適切です。基本的には、レコードセットをループしますが、データを書き込む実際の動作は最後にコミットするまで行われないため、はるかに高速です。

これは、試すためのアクセス側の非常に基本的な例です。

Private Sub TestTrans()

Dim wksp    As DAO.Workspace
Dim rs      As DAO.Recordset

    Set wksp = DBEngine.Workspaces(0) 'The current database

    wksp.BeginTrans 'Start the transaction buffer

    Set rs = CurrentDb.OpenRecordset("Table1", dbOpenDynaset)

    Do 'Begin your loop here

    With rs
        .AddNew
            !Field = "Sample Data"
        .Update
    End With

    Loop 'End it here

    wksp.CommitTrans 'Commit the transaction to dataset

End Sub
于 2012-10-17T09:35:08.153 に答える
4

OK、ばかげて。少しいじくり回した後、

Set Cn = New ADODB.Connection
With Cn
.Provider = "Microsoft.ACE.OLEDB.12.0"
.CursorLocation = adUseClient
.Open MyConn
End With

ループの少し外側にあると、はるかに高速になります。

于 2012-10-17T09:07:53.117 に答える