我在运行一个嵌套循环。我加了一个数组来加速它。
当我在“Active”工作表中有100行41列数据,在“Closed”工作表中有1000行41列数据时,将数据输出到“CompSheet”中大约需要七分钟。
Sub CompareColumns()
'Turn off screen updating and automatic calculation
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Dim i As Integer 'variable for the outer loop
Dim j As Integer 'variable for the inner loop
Dim ws As Worksheet 'variable for the sheet CompSheet
Dim compareLat As Byte 'variable for the column that is being compared
Dim compareLon As Byte 'variable for the column that is being compared
Dim compareLatArray As Byte
Dim compareLonArray As Byte
Dim uniqueID As String 'variable for the unique identifier
Dim ActiveSheetRows As Integer
Dim ClosedSheetRows As Integer
Dim closedArray As Variant ' variable for closed sheet data
Dim closedArrayRow As Variant
Dim activeArray As Variant ' variable for active sheet data
Dim activeArrayRow As Variant
Dim dLon As Double
Dim x As Double
Dim y As Double
Dim lat_a As Double
Dim lat_c As Double
Dim lon_a As Double
Dim lon_c As Double
Dim result As Double
Dim distance_toggle As Single
Dim distance As Single
ActiveSheetRows = Worksheets("Active").UsedRange.Rows.Count
ClosedSheetRows = Worksheets("Closed").UsedRange.Rows.Count
compareLat = 38 'change this variable to switch the column that is being compared
compareLon = 39 'change this variable to switch the column that is being compared
compareLatArray = 38 'change this variable to switch the column that is being compared
compareLonArray = 39 'change this variable to switch the column that is being compared
distance_toggle = 1.5
'Store the data from the "Closed" worksheet into the array
closedArray = Worksheets("Closed").UsedRange.Value
'Store the data from the "Active" worksheet into the array
activeArray = Worksheets("Active").UsedRange.Value
'Check if the sheet CompSheet exists, if not create it
On Error Resume Next
Set ws = ThisWorkbook.Sheets("CompSheet")
If ws Is Nothing Then
ThisWorkbook.Sheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)).Name = "CompSheet"
'copy the header row from the "Closed" worksheet when it first creates the "CompSheet" worksheet
Worksheets("Closed").Rows(1).Copy _
Destination:=Worksheets("CompSheet").Range("A1")
'Add the column header "uniqueID" to the last cell in row 1 of the "CompSheet" worksheet
Worksheets("CompSheet").Cells(1, Worksheets("CompSheet").UsedRange.Columns.Count + 1).Value = "uniqueID"
'Add the column header "CompDistance" to the last cell in row 1 of the "CompSheet" worksheet
Worksheets("CompSheet").Cells(1, Worksheets("CompSheet").UsedRange.Columns.Count + 1).Value = "CompDistance"
End If
On Error GoTo 0
'Loop through all the rows in the "Active" worksheet starting on row 2
For i = 2 To UBound(activeArray, 1)
'Loop through the array to look up the data in the "Closed" worksheet
For j = 2 To UBound(closedArray, 1)
lat_a = activeArray(i, compareLat)
lat_c = closedArray(j, compareLatArray)
lon_a = activeArray(i, compareLon)
lon_c = closedArray(j, compareLonArray)
'Calculationg for D2R = 0.0174532925199433
'pi = 4 * Atn(1)
'D2R = pi / 180#
lat_a = 0.0174532925199433 * lat_a
lat_c = 0.0174532925199433 * lat_c
dLon = 0.0174532925199433 * (lon_c - lon_a)
x = Sin(lat_a) * Sin(lat_c) + Cos(lat_a) * Cos(lat_c) * Cos(dLon)
y = Sqr((Cos(lat_c) * Sin(dLon)) ^ 2 + (Cos(lat_a) * Sin(lat_c) - Sin(lat_a) * Cos(lat_c) * Cos(dLon)) ^ 2)
distance = WorksheetFunction.Atan2(x, y) * 3963.19
If distance <= distance_toggle Then
'Copy the row from the Closed worksheet to the CompSheet worksheet in the next available row
Worksheets("CompSheet").Rows(Worksheets("CompSheet").UsedRange.Rows.Count + 1).Insert
closedArrayRow = Worksheets("Closed").Cells(j, 1).Resize(1, UBound(closedArray, 2))
'Worksheets("CompSheet").Range("B1").Resize(UBound(closedArrayRow, 1), UBound(closedArrayRow, 2)).Value = closedArrayRow
Worksheets("CompSheet").Rows(Worksheets("CompSheet").UsedRange.Rows.Count).Resize(1, 41).Value = closedArrayRow
'Create a uniqueID by combining column 6 from both the Active and Closed worksheets with a space and "&" in between
uniqueID = activeArray(i, 5) & " " & "&" & " " & closedArray(j, 5)
'Paste the uniqueID in the next available column of the new row in the CompSheet worksheet
Worksheets("CompSheet").Cells(Worksheets("CompSheet").UsedRange.Rows.Count, compareLon + 1).Value = uniqueID
'Paste the distance value in the corresponding column of the new row in the CompSheet worksheet
Worksheets("CompSheet").Cells(Worksheets("CompSheet").UsedRange.Rows.Count, compareLon + 2).Value = distance
End If
Next j
Next i
'Formatting "CompSheet" Data
Worksheets("CompSheet").Columns.AutoFit
Worksheets("CompSheet").Range("AO:AO").NumberFormat = "#,##0.0"
Worksheets("CompSheet").UsedRange.Font.Bold = False
Worksheets("CompSheet").Cells(1, 1).EntireRow.Font.Bold = True
'Turn on screen updating and automatic calculation
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
除了数组,我还添加了其他代码,例如:
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Excel文件的Google驱动器链接. https://drive.google.com/file/d/1GfR5RbWcHFQC-5oY9izDOQWbzZkvBwXi/view?usp=share_link
我的代码花了8分钟。我想把它放大到这个数据集的500倍。基于线性时间计算,这将需要60个小时来运行。
我试图比较真实的地产上市(物业),物业目前上市销售的“活动”表中的那些已经售出,在“关闭”表。
对于“活动”表中的每个属性(行),我需要根据距离切换检查“已关闭”表中的每个已售出属性,如果已售出属性在指定距离(2英里)内,则我希望将已售出列表行从“已关闭”表复制到“CompSheet”中,并粘贴唯一ID(两个地址连接)和“距离”变量,以便进行比较。
4条答案
按热度按时间nue99wik1#
应在10秒内完成
fnvucqvd2#
到目前为止,我发现不需要的一件事是:
这看起来像是你在底部添加了一行。你不需要在底部添加行,它们已经在那里了--只需要注解掉它,然后在“copy”语句中添加1,Rows.Count + 1。
31moq8wy3#
这个应该更快编译过了但未经测试。
WorksheetFunction
调用替换为更快的VBA版本。Insert
(如Nick所建议)。Const
表示固定值UsedRange
,因为它可能不可靠/不可预测iyr7buue4#
你可以做一些基本的事情来加速代码。最简单的是禁用屏幕更新和计算。你可以使用错误处理来确保它们被重新启用。
有些人喜欢把它放到一些帮助函数中,甚至放在一个类中来管理多个进程的状态。
长时间运行进程最常见的原因是阅读和写入单元格。读取数组比读取范围内的单个单元格要快得多。
请考虑以下几点:
这将花费非常非常长的时间。现在让我们用一个数组来做。读一次,写一次。不需要禁用屏幕更新或设置计算为手动。这将是一样快的。
您的代码看起来仍在循环中执行读/写操作,这是导致您的速度变慢的原因。