大数据上传到服务器,更好的块?

时间:2013-07-08 15:42:31

标签: excel excel-vba vba

我继承了一组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

任何建议表示赞赏。我试图保持简短,但是当你不知道自己到底在做什么或者走向何方时,这很难。

1 个答案:

答案 0 :(得分:1)

根据我们的对话以及我认为您的代码的工作方式,这里有一个未经测试的解决方案,您可以通过将大量处理移动到SQL来加快速度。不幸的是,您必须跳过已有的记录集处理方法。根据谷歌的说法,你不能使用ADO.Recordset作为SQL查询的来源(它们位于内存的不同部分,彼此之间没有看到)。所以,你可以试试这个:

  1. 在SQL Server上创建临时表。我们称之为TblStaging,因为为什么不呢。此临时表的数据类型只是大字符串字段,因此它可以容纳您放入其中的任何内容,包括错误。

  2. 在声明连接字符串之后,尝试使用JosieP建议的Insert语句将数据加载到TblStaging。之后评论所有VBA。

  3. 创建一个.sql文件,该文件将根据VBA中的规则验证您的数据,然后将其移动到永久SQL表中。 (我假设你知道足够多的SQL能够做到这一点。)因为现在所有这些都在SQL而不是VBA中,所以它应该更快。

  4. 必须以某种方式运行此sql文件。如果你不想每次都手动执行,有2个选项(假设你对SQL Server足够好):
    4A。弄清楚如何从命令行运行.sql并运行从VBA调用该命令行的批处理文件 4B。将其设置为定期重复代理。