我已經繼承了一組excel VBA宏,它們從電子表格中抓取數據並將數據上傳到數據庫(SQL DB)。問題是數據「很大」(特定表單上的46列* 10,500行)需要的瘋狂時間。在我看來,將數據分塊到數據庫會更好,但這是正確的嗎?如果是這樣,那麼最好的方法是什麼?我目前正在嘗試在for循環中封裝下面的代碼,將它分成500行,但它並不優雅,因爲vba不是我的特長。大數據上傳到服務器,更好的塊?
Sub Upload_Claims()
Dim SubmissionNumber As Integer
Dim LoopVar As Integer, row As Integer
Set cnnConn = New ADODB.Connection
cnnConn.ConnectionString = "driver={SQL Server};server=" & Server & ";database=happyfunserver"
cnnConn.Open
SubmissionNumber = Sheets("Quality Check").Range("SubID").Value
'Upload HPL - PPL
Set cmdCommand = New ADODB.Command
Set cmdCommand.ActiveConnection = cnnConn
With cmdCommand
.CommandText = "Select * from losses where submission_id = " & SubmissionNumber
.CommandType = adCmdText
.Execute
End With
' Open the recordset.
Set rstRecordset = New ADODB.Recordset
Set rstRecordset.ActiveConnection = cnnConn
rstRecordset.Open cmdCommand, , adOpenStatic, adLockBatchOptimistic
'upload '
Sheets("PL").Select
row = 8
Do While Range("C" & row).Value <> vbNullString
With rstRecordset
.AddNew
.Fields("submission_id") = SubmissionNumber
If Range("A" & row).Value <> vbNullString Then
.Fields("tag_id") = Range("A" & row).Value
End If
If Range("B" & row).Value <> vbNullString Then
.Fields("batch_tag_id") = Range("B" & row).Value
End If
If Range("C" & row).Value <> vbNullString Then
.Fields("source") = Left(Range("C" & row).Value, 250)
End If
If IsDate(Range("D" & row).Value) Then
.Fields("evaluation_date") = Range("D" & row).Value
End If
If Range("E" & row).Value <> vbNullString Then
If Range("E" & row).Value = "HPL" Then
.Fields("coverage_type_id") = 22
ElseIf Range("E" & row).Value = "PL" Then
.Fields("coverage_type_id").Value = 2
End If
End If
'--------------'
If Range("F" & row).Value <> vbNullString Then
.Fields("claim_no") = Left(Range("F" & row).Value, 250)
End If
If Range("G" & row).Value <> vbNullString Then
.Fields("claimant") = Left(Range("G" & row).Value, 200)
End If
'upload layer'
If Range("H" & row).Value <> vbNullString Then
If UCase(Range("H" & row).Value) = "UNKNOWN" Then
.Fields("layer_id") = 0
ElseIf UCase(Range("H" & row).Value) = "AAA" Then
.Fields("layer_id") = 1
ElseIf UCase(Range("H" & row).Value) = "BBBBBB" Then
.Fields("layer_id") = 2
ElseIf UCase(Range("H" & row).Value) = "CCCCC" Then
.Fields("layer_id") = 3
ElseIf UCase(Range("H" & row).Value) = "DDDDDDDD" Then
.Fields("layer_id") = 4
ElseIf UCase(Range("H" & row).Value) = "EEE" Then
.Fields("layer_id") = 5
End If
End If
'-------------------'
If Range("I" & row).Value <> vbNullString Then
.Fields("aaaaaaaa_name") = Left(Range("I" & row).Value, 100)
End If
If IsNumeric(Range("J" & row).Value) And Range("J" & row).Value <> 0 Then
.Fields("bbb_id") = Left(Range("J" & row).Value, 7)
End If
If Not IsError(Range("K" & row).Value) Then
.Fields("ccc_id_verified") = Range("K" & row).Value
End If
If Not IsError(Range("L" & row).Value) Then
If Range("L" & row).Value <> vbNullString And Range("L" & row).Value <> 0 Then
.Fields("dddddddd_city") = Left(Range("L" & row).Value, 80)
End If
End If
If Range("M" & row).Value <> vbNullString And Range("M" & row).Value <> 0 Then
.Fields("eeeeeeee_fips") = Left(Range("M" & row).Value, 5)
End If
If Not IsError(Range("N" & row).Value) Then
If Range("N" & row).Value <> vbNullString And Range("N" & row).Value <> 0 Then
.Fields("ffffffff_stateabbr") = Left(Range("N" & row).Value, 2)
End If
End If
If IsDate(Range("O" & row).Value) Then
.Fields("gggggggg_date") = Range("O" & row).Value
End If
If IsDate(Range("P" & row).Value) Then
.Fields("hhhhhh_date") = Range("P" & row).Value
End If
If IsNumeric(Range("Q" & row).Value) Or Range("Q" & row).Value = 0 Then
.Fields("iiiiiiiii_paid") = Range("Q" & row).Value
End If
If IsNumeric(Range("R" & row).Value) Or Range("R" & row).Value = 0 Then
.Fields("jjjjjjjjj_reserve") = Range("R" & row).Value
End If
If IsNumeric(Range("S" & row).Value) Or Range("S" & row).Value = 0 Then
.Fields("kkkk_paid") = Range("S" & row).Value
End If
If IsNumeric(Range("T" & row).Value) Or Range("T" & row).Value = 0 Then
.Fields("llll_reserve") = Range("T" & row).Value
End If
'upload claim status'
If Range("U" & row).Value <> vbNullString Then
If UCase(Range("U" & row).Value) = "CLOSED" Then
.Fields("status_id") = 1
ElseIf UCase(Range("U" & row).Value) = "OPEN" Then
.Fields("status_id") = 0
ElseIf UCase(Range("U" & row).Value) = "REOPEN" Then
.Fields("status_id") = 2
End If
End If
'---------------------------'
If IsDate(Range("V" & row).Value) Then
.Fields("closed_date") = Range("V" & row).Value
End If
If Range("W" & row).Value <> vbNullString Then
.Fields("description") = Range("W" & row).Value
End If
If IsNumeric(Range("AN" & row).Value) Then
.Fields("manual") = Range("AN" & row).Value
End If
If IsNumeric(Range("AB" & row).Value) Then
.Fields("11111") = Range("AB" & row).Value
End If
If IsNumeric(Range("AC" & row).Value) Then
.Fields("2222222") = Range("AC" & row).Value
End If
If IsNumeric(Range("AD" & row).Value) Then
.Fields("33333333333") = Range("AD" & row).Value
End If
If IsNumeric(Range("AE" & row).Value) Then
.Fields("444444444") = Range("AE" & row).Value
End If
If IsNumeric(Range("AF" & row).Value) Then
.Fields("55555555") = Range("AF" & row).Value
End If
If IsNumeric(Range("AG" & row).Value) Then
.Fields("666666666") = Range("AG" & row).Value
End If
If IsNumeric(Range("AH" & row).Value) Then
.Fields("7777777777777") = Range("AH" & row).Value
End If
If IsNumeric(Range("AI" & row).Value) Then
.Fields("other") = Range("AI" & row).Value
End If
If IsNumeric(Range("AJ" & row).Value) Then
.Fields("88") = Range("AJ" & row).Value
End If
If IsNumeric(Range("AK" & row).Value) Then
.Fields("cause") = Range("AK" & row).Value
End If
If IsNumeric(Range("AL" & row).Value) Then
.Fields("dept") = Range("AL" & row).Value
End If
If IsNumeric(Range("AM" & row).Value) Then
.Fields("outcome") = Range("AM" & row).Value
End If
If IsNumeric(Range("AS" & row).Value) Then
.Fields("report_lag") = Range("AS" & row).Value
End If
If IsNumeric(Range("AT" & row).Value) Then
.Fields("closed_lag") = Range("AT" & row).Value
End If
.Update
End With
row = row + 1
If row Mod 25 = 0 Then
Application.StatusBar = "PL" & " - " & row
DoEvents
End If
Loop
Application.StatusBar = "Performing " & "PL" & " Batch Update..."
rstRecordset.UpdateBatch
'(Similar loop repeats for 5 different pieces)
End Sub
任何意見表示讚賞。我試圖保持簡短,但是當你不知道自己在做什麼或者要走什麼方向時很難。
我估計處理記錄將總是慢 - 你會被更好地使用單個查詢具有閉合工作簿作爲數據源:'cnnConn.Execute「INSERT INTO損失(C1,C2,C3) SELECT * FROM [Excel 12.0; HDR = YES; Database = C:\ Development \ MyImport.xlsm]。[Sheet1 $]「'如果可以的話 – JosieP
一個選項可能是將sql插入或更新語句寫入.sql文件可以直接在整個事務的最後一次提交對數據庫執行。插入或更新大約10k行不應該花很長時間。 – ChrisProsser
這些是一些有趣的字段名稱。 「gggggggg_date」? 「7777777777777」?只是好奇。在發佈代碼之前,您是否隱藏了匿名代碼或者實際上是字段名稱? – PowerUser