excel - VBA 优化工作表数据传输
问题描述
我的代码有效,但在工作表 1 上的 36000 行和工作表 2 上的 10000 行上执行需要 3 个多小时。我想要另一种方法来更改另一个工作表中两个单元格相等的两个单元格数据。
Sub test_function()
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Set ws1 = ThisWorkbook.Sheets("Sheet1")
Set ws2 = ThisWorkbook.Sheets("Sheet2")
line_count1 = ws1.Range("A1").End(xlDown).row
line_count2 = ws2.Range("A1").End(xlDown).row
For i = 2 To line_count1
For j = 2 To line_count2
If CStr(ws1.Range("d" & i).Value) = CStr(ws2.Range("c" & j).Value) And CStr(ws1.Range("f" & i).Value) = CStr(ws2.Range("e" & j).Value) Then
ws1.Range("q" & i).Value = ws2.Range("a" & j).Value
ws1.Range("r" & i).Value = ws2.Range("b" & j).Value
End If
Next j
Next i
End Sub
解决方案
尝试这个:
Sub test_function()
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Set ws1 = ThisWorkbook.Sheets("Sheet1")
Set ws2 = ThisWorkbook.Sheets("Sheet2")
line_count1 = ws1.Range("A1").End(xlDown).Row
line_count2 = ws2.Range("A1").End(xlDown).Row
Dim r2() As Variant
Dim r1() As Variant
' get all data from both ranges
r2 = ws2.Range("a2:e" & line_count2)
r1 = ws1.Range("d2:r" & line_count1)
For i = 2 To line_count1
For j = 2 To line_count2
If CStr(r1(1, i)) = CStr(r2(3, j)) And CStr(r1(3, i)) = CStr(r2(5, j)) Then
r1(13, i) = r2(1, j)
r1(14, i) = r2(2, j)
End If
Next j
Next i
'paste the changed range1 back
ws1.Range("d2:r" & line_count1) = r1
End Sub
这显示了如何执行与原始代码相同的操作,但使用范围数组复制而不是浏览单个单元格。这可能不是最有效的方法(因为它仍在复制许多不必要的单元格),但它应该更快。
更新:
好的,现在这个版本对于这个任务来说可能是尽可能快的:
Sub Fast_test_function()
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Set ws1 = ThisWorkbook.Sheets("Sheet1")
Set ws2 = ThisWorkbook.Sheets("Sheet2")
line_count1 = ws1.Range("A1").End(xlDown).Row
line_count2 = ws2.Range("A1").End(xlDown).Row
' copy each needed column into an array
Dim d1(), f1(), q1(), r1(), c2(), e2(), a2(), b2()
d1 = ws1.Range("d1:d" & line_count1)
f1 = ws1.Range("f1:f" & line_count1)
q1 = ws1.Range("q1:q" & line_count1)
r1 = ws1.Range("r1:r" & line_count1)
c2 = ws2.Range("c1:c" & line_count2)
e2 = ws2.Range("e1:e" & line_count2)
a2 = ws2.Range("a1:a" & line_count2)
b2 = ws2.Range("b1:b" & line_count2)
' load the lookup collections
Dim sKey As String, i As Long, j As Long, str As String
Dim colA2 As New Collection, colB2 As New Collection
On Error Resume Next ' ignore duplicate key errors
For j = 2 To line_count2
sKey = CStr(c2(j)) & "~" & CStr(e2(j))
colA2.Add CStr(a2(j)), sKey
colB2.Add CStr(b2(j)), sKey
Next j
' set the output array values
For i = 2 To line_count1
sKey = CStr(d1(i)) & "~" & CStr(f1(i))
On Error Resume Next ' suppress Missing Key errors
str = colA2(sKey)
If Err.Number = 0 Then
q1(i) = str
str = colB2(sKey)
r1(i) = str
End If
Next i
On Error GoTo 0
' copy the output arrays back to the output ranges
ws1.Range("q1:q" & line_count1) = q1
ws1.Range("r1:r" & line_count1) = r1
End Sub
尽管使用字典而不是集合的版本可能会稍微快一些。
推荐阅读
- python-3.x - 为什么 pd.ExcelWriter 在设置 mode='a' 时如果不存在则无法创建新文件
- linux-kernel - 未知符号:kmem_cache_alloc_trace
- ios - 如何正确使用 swift 语句更改 IBAction 按钮的操作?
- c++ - 在运行时链接的模型依赖目标
- c - 使用stm32f407板控制无刷直流电机
- c++ - 在 Qml 中从字节数组加载到图像
- cucumber - 如何在宁静中运行多个标签?
- nestjs - 循环依赖试图验证 typeorm 实体
- codeigniter - 会话数据未保存在 Codeigniter Rest API 上
- cpu-architecture - 使用内存映射 IO 时 DMA 是如何物理完成的