简体   繁体   English

在VBA Excel中复制大量数据

[英]Copying big amount of data in VBA excel

I would like to be able to copy around 30k rows (to be exact, just some elements of the rows) from sheet A to sheet B, starting the destination from row nr 36155. Sometimes, we copy the row more than once, depending on the number in the G column. 我希望能够从工作表A到工作表B复制大约30k行(准确地说,只是行中的某些元素),从目标行nr 36155开始。有时,我们会复制该行多次,具体取决于G列中的数字。 This is the macro I've written: 这是我编写的宏:

Sub copy()
ActiveSheet.DisplayPageBreaks = False
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculate

Dim k As Long, k1 As Long, i As Integer

k = 36155
k1 = 30000

For i = 1 To k1
For j = 1 To Sheets("A").Range("G" & i + 2).Value
    Sheets("B").Range("A" & k).Value = Sheets("A").Range("A" & i + 2).Value
    Sheets("B").Range("B" & k).Value = Sheets("A").Range("B" & i + 2).Value
    Sheets("B").Range("C" & k).Value = j
    Sheets("B").Range("D" & k).Value = Sheets("A").Range("C" & i + 2).Value
    Sheets("B").Range("E" & k).Value = Sheets("A").Range("D" & i + 2).Value
    Sheets("B").Range("F" & k).Value = Sheets("A").Range("E" & i + 2).Value
    Sheets("B").Range("G" & k).Value = Sheets("A").Range("F" & i + 2).Value
    Sheets("B").Range("H" & k).Value = Sheets("A").Range("I" & i + 2).Value + (j - 1) * Sheets("A").Range("H" & i + 2).Value
    Sheets("B").Range("I" & k).Value = Sheets("A").Range("J" & i + 2).Value
    k = k + 1
Next j
Next i


Application.EnableEvents = True
Application.CutCopyMode = False
Application.ScreenUpdating = True
End Sub

Unfortunately, this macro takes a lot of time to run (around 10 minutes). 不幸的是,此宏需要大量时间才能运行(大约10分钟)。 I have a feeling that, there may be a better way to do that.. Do you have any ideas, how can we enchance the macro? 我感觉可能有更好的方法来执行此操作。您是否有任何想法,我们如何使宏具有吸引力?

I would suggest you read your data into a recordset as shown here , then loop the recordset. 我建议您将数据读入记录集,如下所示 ,然后循环记录集。

Try the following (untested). 请尝试以下操作(未经测试)。

Sub copy()

    With Application
        .ScreenUpdating = False
        .EnableEvents = False
        .Calculate
        .Calculation = xlCalculationManual
    End With

    Dim k As Long, i As Integer

    k = 36155

    ' read data into a recordset
    Dim rst As Object
    Set rst = GetRecordset(ThisWorkbook.Sheets("A").UsedRange) 'feel free to hard-code your range here

    With rst
        While Not .EOF

            For j = 1 To !FieldG
          ' !FieldG accesses the Datafield with the header "FieldG". Change this to the header you actually got in Column G, like "!MyColumnG" or ![columnG with blanks]

                Sheets("B").Cells(k, 1).Value = !FieldA
                ' ... your code

                k = k + 1
            Next j

            .movenext
        Wend

    End With


    With Application
        .EnableEvents = True
        .ScreenUpdating = True
        .Calculation = xlCalculationAutomatic
    End With

End Sub

Also add the following Function into your VBA Module. 还将以下功能添加到您的VBA模块中。

Function GetRecordset(rng As Range) As Object

    'Recordset ohne Connection:
    'https://usefulgyaan.wordpress.com/2013/07/11/vba-trick-of-the-week-range-to-recordset-without-making-connection/

    Dim xlXML As Object
    Dim rst As Object

    Set rst = CreateObject("ADODB.Recordset")
    Set xlXML = CreateObject("MSXML2.DOMDocument")
    xlXML.LoadXML rng.Value(xlRangeValueMSPersistXML)

    rst.Open xlXML

    Set GetRecordset = rst

End Function

Note: - using a recordset gives you additional options like filtering data - with a recordset, your not dependent on the column-order of your input-data, meaning you don't have to adjust your macro if you decide to add another column to sheet A (as long as you keep the headers the same) 注意: -使用记录集为您提供了其他选项,例如过滤数据-使用记录集,您不必依赖输入数据的列顺序,这意味着如果决定添加另一列,则不必调整宏。工作表A(只要您保持标题相同)

Hope this helps. 希望这可以帮助。

Try this using variant arrays: could be even faster if you can use a B array containing more than 1 row. 使用变体数组进行尝试:如果可以使用包含多于1行的B数组,则速度可能更快。 This version takes 17 seconds on my PC. 此版本在我的PC上需要17秒。

Sub Copy2()
    ActiveSheet.DisplayPageBreaks = False
    Application.ScreenUpdating = False
    Application.EnableEvents = False
    Application.Calculate
    '
    Dim k As Long, k1 As Long, i As Long, j As Long
    Dim varAdata As Variant
    Dim varBdata() As Variant
    '
    Dim dT As Double
    '
    dT = Now()
    '
    k = 36155
    k1 = 30000
    '
    ' get sheet A data into variant array
    '
    varAdata = Worksheets("A").Range("A1:J1").Resize(k1 + 2).Value2
    '
    For i = 1 To k1
        'For j = 1 To Sheets("A").Range("G" & i + 2).Value
        For j = 1 To varAdata(i + 2, 7)
            '
            ' create empty row of data for sheet B and  fill from variant array of A data
            '
            ReDim varBdata(1 to 1,1 to 9) As Variant
            'Sheets("B").Range("A" & k).Value = Sheets("A").Range("A" & i + 2).Value
            varBdata(1, 1) = varAdata(i + 2, 1)
            varBdata(1, 2) = varAdata(i + 2, 2)
            varBdata(1, 3) = j
            varBdata(1, 4) = varAdata(i + 2, 3)
            varBdata(1, 5) = varAdata(i + 2, 4)
            varBdata(1, 6) = varAdata(i + 2, 5)
            varBdata(1, 7) = varAdata(i + 2, 6)
            varBdata(1, 8) = varAdata(i + 2, 9) + (j - 1) * varAdata(i + 2, 8)
            varBdata(1, 9) = varAdata(i + 2, 10)
            '
            ' write to sheet B
            '
            Sheets("B").Range("A1:I1").Offset(k - 1).Value2 = varBdata
            k = k + 1
        Next j
    Next i
    '
    Application.EnableEvents = True
    Application.CutCopyMode = False
    Application.ScreenUpdating = True
    MsgBox (Now() - dT)
End Sub

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM