【发布时间】:2015-04-24 18:07:34
【问题描述】:
我写了一些代码,计算时间太长了。
它从工作表中“刷”特定列中的行(Plan1,有 11,617 行,从第二行开始数据),查找单元格的值,存储该值,在一秒钟内搜索特定列中的每一行工作表(Plan2,有 158,715 行,也从第 2 行开始数据)并验证遇到的值是否与搜索的值匹配。如果为 true,则存储该值,然后将其分配给上一个工作表 (Plan1) 中未使用的单元格,在同一行但在新列中。它可以工作,但由于行数很大,因此完成 Plan1 中的每一列大约需要 1 小时。
有一次,我尝试使用 VLOOKUP,它花费的时间非常少(大约 5 分钟),但是数据异常损坏,所以我开始使用 VBA 编程来获得更高的数据准确性。我抬头看了看this question,但我的问题比答案的解释太具体了。我翻译了代码以便更好地理解,所以如果您发现语法错误,请不要担心;这段代码在翻译之前就可以工作。
最后,这是我的代码。
Sub AddAddress()
Dim Plan1, Plan2 As Worksheet
Dim FirstRow As Long
Dim LastRow As Long
Dim CurrentRow As Long
Dim CalcMode As Long
Dim ViewMode As Long
Dim SoughtId, EncounteredId, Address As String
Dim SuccessCounter As Integer
Dim StartTime, EndTime, ElapsedTime As Date
StartTime = Time()
Set Plan1 = Application.Worksheets("Plan1")
Set Plan2 = Application.Worksheets("Plan2")
'Define calculation mode
With Application
CalcMode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
End With
'Use Plan1
With Plan1
'Select this worksheet
.Select
'Memory optimization
ViewMode = ActiveWindow.View
ActiveWindow.View = xlNormalView
.DisplayPageBreaks = False
'First and last rows' loop
FirstRow = .UsedRange.Cells(1).Row
LastRow = .UsedRange.End(xlDown).Row
'Loop execution
For CurrentRow = LastRow To FirstRow Step -1
'Check Id value in A column
With .Cells(CurrentRow, "A")
'Store SoughtId
SoughtId = .Value
'Search Address via Id on Plan2
With Plan2
.Select
Dim ActiveCell As String
With .Range("D:D")
'Search Id
If (SoughtId = .Find(SoughtId)) Then
EncounteredId = SoughtId
End If
ActiveCell = .Find(SoughtId).Address
End With
'Define/store Address
With .Range(ActiveCell)
'Being in current column, go to the column that
'contains the wanted value if this value is not empty
If .Offset(0, 9).Value <> "" Then
Address = .Offset(0, 9).Value
End If
End With
End With
Plan1.Select
'Append Address obtained value in corresponding row's cell
'and increment SuccessCounter
With .Offset(0, 15)
.Value = Address
End With
SuccessCounter = SuccessCounter + 1
End With
Next CurrentRow
End With
ActiveWindow.View = ViewMode
With Application
.ScreenUpdating = True
.Calculation = CalcMode
End With
EndTime = Time()
ElapsedTime = EndTime - StartTime
MsgBox "Operation finished!" & vbNewLine & vbNewLine & "Added addresses: " & SuccessCounter & vbNewLine & "Time elapsed: " & ElapsedTime
End Sub
【问题讨论】:
-
我不会在如此大的工作表 (Plan2) 上重复使用 Find(),而是使用字典查找。在此处查看我的示例:stackoverflow.com/questions/14265919/…
-
您的数据实际上是从第 1 行开始,还是有列标题标签,而实际数据从第 2 行开始?
-
@TimWilliams 我现在正在评估你的答案,很快就会给你一个简报。
-
@Jeeped 我编辑了帖子来回答你的问题