提高宏循环的速度,以便在c上进行数据转换。 76,000行数据

时间:2017-06-26 09:38:52

标签: excel vba performance excel-vba

我尝试了两种不同的配置电子表格工具的方法,用于将客户端提供的数据转换为我们自己的数据代码。

数据集可能会特别大(这一行是76,335行),因此宏观性能非常重要。

我尝试的第一种方法是将一系列索引/匹配公式记录到VBA中,并将代码插入到列M到Y中并向下拖动到原始数据集中最后一行的任何位置(存在于Col A到J)。这些公式中只有一个是数组公式,我尝试了没有数组公式的代码,总体效益很小。这种方法(让我们称之为方法A)花了14分8秒(带有i7-2600 CPU和8 GB RAM的Windows PC)。

如果我让VBA进行excel公式所做的计算,我认为它会提高性能,我运行了以下循环(方法B)。

Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
Application.EnableEvents = False

lastRow = ActiveSheet.Cells(Rows.Count, "F").End(xlUp).Row

For i = 6 To lastRow

    With ThisWorkbook.Worksheets("CONVERSION")

        If Range("M" & i) = "BIN" Then
            Range("N" & i) = "Duplicate"
        Else
            Range("N" & i) = Range("B" & i) & "-" & Range("D" & i) & "-" & Range("M" & i)
        End If

        If Range("B" & i) = "Duplicate" Then
            Range("O" & i) = "D"
            Else
            Range("O" & i) = "N"
        End If

        If Range("E2") = "Groundwater" Then
            Range("P" & i) = "WG"
            ElseIf Range("E2") = "Leachate" Then
            Range("P" & i) = "LE"
            ElseIf Range("E2") = "Surface water" Then
            Range("P" & i) = "WS"
            Else
            Range("P" & i) = "Other"
        End If

        'Plus another six If statements similar to the above to populate Cols P to Y... Not included here to keep this code on StackOverflow easier to read

    End With

Next i

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

这令人惊讶地花了27分27秒。尽管有Application.Calculation = xlCalculationManualApplication.ScreenUpdating = FalseApplication.EnableEvents = False

为什么VBA计算方法较慢?这与我的循环效率低下有关吗?可能是因为VBA必须反复回访电子表格的值,来回吗?

一般的引导和建议将不胜感激。我知道我有一个大型数据集,但我希望能够以超过14分钟的速度运行此转换代码。

1 个答案:

答案 0 :(得分:2)

您需要使用数组 - 我已经切换了您的代码并将所有内容弹出到数组中以完成大部分工作:

Sub SpeedUp()
Dim iLastRow As Long, iLastCol As Long, i As Long
Dim Arry() As Variant

Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
Application.EnableEvents = False

iLastRow = ActiveSheet.Cells(Rows.Count, "F").End(xlUp).Row
iLastCol = ActiveSheet.Cells(5, Columns.Count).End(xlToLeft).Column 'I'm assuming Row 1 is the header row. Also, if you're creating colums (to column Y) then just change this to "iLastCol = 25"

ReDim Arry(1 To iLastRow, 1 To iLastCol) ' This array is a 2 dimensionnel array and you can referance rows/columns within it like you would using Cells([Row number],[Column number])
Arry = Range(Cells(1, 1), Cells(iLastRow, iLastCol))

For i = 6 To iLastRow
    If Arry(i, 13) = "BIN" Then '13 corresponds to column M
        Arry(i, 14) = "Duplicate"
    Else
        Arry(i, 14) = Arry(i, 2) & "-" & Arry(i, 4) & "-" & Arry(i, 13)
    End If

    If Arry(i, 2) = "Duplicate" Then
        Arry(i, 15) = "D"
        Else
        Arry(i, 15) = "N"
    End If

    If Arry(i, 5) = "Groundwater" Then
        Arry(i, 16) = "WG"
        ElseIf Arry(i, 5) = "Leachate" Then
        Arry(i, 16) = "LE"
        ElseIf Range("E2") = "Surface water" Then
        Arry(i, 16) = "WS"
        Else
        Arry(i, 16) = "Other"
    End If

'Plus another six If statements similar to the above to populate Cols P to Y... Not included here to keep this code on StackOverflow easier to read
Next i

ThisWorkbook.Worksheets("CONVERSION").Range(Cells(1, 1), Cells(iLastRow, iLastCol)) = Arry ' Sets all the values

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

End Sub