我正在开发一个由一系列表单和几个宏组成的大型项目。我需要逐月更新的主要报告是21K行并且还在增长。它在12个单独的列中收集所有12个月的更新。要完成"更新",我必须匹配列#34; A"中包含的主文件中的部件号(21k行是所有部件号及其信息),并将其与另一个匹配由部件号生成的报告(此时间包含在列#34; B"中)如果匹配(需要与之匹配),请返回以下内容:
将第9列sht1的值放入由变量
指定的sht列将第7列sht1的值放在sht第27列
将第11列的值sht 1置于第34列
每次匹配时,逐行循环,直到列A中包含的最后一个部件号为止。
以下代码有效,但我想知道我应该写一个更好的方法吗?这是处理速度和准确性的最佳选择吗?我刚刚在另一个代码块中意识到,同样的方法没有执行完全匹配,现在已经抛出一个红旗,让我可能改变我的方法。我绝对需要这个准确,它必须完全匹配,或将内容留空。
'Set variable with cell range value for ABC Code based on month selected by User
Dim ABCCodeCell As Integer
Dim wb1 As Workbook
Dim wb2 As Workbook
Dim sht1 As Worksheet
Dim sht As Worksheet
Dim lRow As Long
Dim rng As Range
Set wb1 = Workbooks(vFileName1) 'ABC Matrix File
Set wb2 = Workbooks(vFileName2) 'Cycle Count Remainder Browse File
Set sht = wb1.Worksheets(1) 'ABC Matrix File
Set sht1 = wb2.Worksheets(1) 'Cycle Count Remainder Browse File
lRow = sht.Cells(sht.Rows.Count, 1).End(xlUp).Row
Select Case ABCMatrixMonthSelect.ComboBox1.value
Case "January": ABCCodeCell = 21
Case "February": ABCCodeCell = 23
Case "March": ABCCodeCell = 25
Case "April": ABCCodeCell = 3
Case "May": ABCCodeCell = 5
Case "June": ABCCodeCell = 7
Case "July": ABCCodeCell = 9
Case "August": ABCCodeCell = 11
Case "September": ABCCodeCell = 13
Case "October": ABCCodeCell = 15
Case "November": ABCCodeCell = 17
Case "December": ABCCodeCell = 19
End Select
'Execute Find (Vlookup)
On Error Resume Next
For i = 2 To lRow
If sht.Cells(i, 1).value <> "" Then
Set rng = sht1.Range("B:B").Find(sht.Cells(i, 1).value)
If Not rng Is Nothing Then
sht.Cells(i, ABCCodeCell).value = sht1.Cells(rng.Row, 9).value
sht.Cells(i, 27).value = sht1.Cells(rng.Row, 7).value
sht.Cells(i, 34).value = sht1.Cells(rng.Row, 11).value
End If
End If
Next
答案 0 :(得分:1)
我不会评论您的代码是否是速度等最佳代码,因为Stack Overflow并不是真正的主题 - 这些问题应该在{{3 }}
然而,我会回答你的问题(需要完全匹配)&#34;注释:
Excel允许用户在执行查找时指定各种选项:
默认情况下,大多数(全部?)这些选项会被记住并在下一个查找中使用,可以是用户执行的手动查找,也可以是VBA代码中编程的Find
。
您当前的查找(sht1.Range("B:B").Find(sht.Cells(i, 1).value)
)未指定What
参数以外的任何参数,因此将使用上次用户使用的LookIn
{{1}的值}和LookAt
参数。
如果您想要执行完全匹配,并且您不相信用户在运行代码之前没有完成部分匹配,则应明确说明您希望使用哪些选项。
我建议您将MatchCase
更改为:
Find
答案 1 :(得分:1)
与使用Find()
相比,在大型循环中运行Match()
非常慢。
例如,在20,000个不同值的列中查找2000个值:
Sub Tester()
Dim i As Long, f As Range, t, m, n As Long
t = Timer
For i = 1 To 2000
Set f = Columns(1).Find(what:="Prod_" & Format(i, "000000"), _
lookat:=xlWhole, LookIn:=xlValues)
If Not f Is Nothing Then
n = n + 1
End If
Next i
Debug.Print "Find", Timer - t, "found " & n
t = Timer
n = 0
For i = 1 To 2000
m = Application.Match("Prod_" & Format(i, "000000"), Columns(1), 0)
If Not IsError(m) Then
n = n + 1
'here m = the row with the matched value, so copy from this row
End If
Next i
Debug.Print "Match", Timer - t, "found " & n
End Sub
输出:
Find 19.75781 found 2000
Match 1.46875 found 2000
答案 2 :(得分:0)
如果sht没有公式单元格,则使用Variant Array会更快。
Sub test()
'Set variable with cell range value for ABC Code based on month selected by User
Dim ABCCodeCell As Integer
Dim wb1 As Workbook
Dim wb2 As Workbook
Dim sht1 As Worksheet
Dim sht As Worksheet
Dim lRow As Long
Dim rng As Range
Set wb1 = Workbooks(vFileName1) 'ABC Matrix File
Set wb2 = Workbooks(vFileName2) 'Cycle Count Remainder Browse File
Set sht = wb1.Worksheets(1) 'ABC Matrix File
Set sht1 = wb2.Worksheets(1) 'Cycle Count Remainder Browse File
lRow = sht.Cells(sht.Rows.Count, 1).End(xlUp).Row
Select Case ABCMatrixMonthSelect.ComboBox1.Value
Case "January": ABCCodeCell = 21
Case "February": ABCCodeCell = 23
Case "March": ABCCodeCell = 25
Case "April": ABCCodeCell = 3
Case "May": ABCCodeCell = 5
Case "June": ABCCodeCell = 7
Case "July": ABCCodeCell = 9
Case "August": ABCCodeCell = 11
Case "September": ABCCodeCell = 13
Case "October": ABCCodeCell = 15
Case "November": ABCCodeCell = 17
Case "December": ABCCodeCell = 19
End Select
'Execute Find (Vlookup)
Dim vDB, rngDB As Range, r As Long, c As Integer '<~~ vDB is Variant array
Dim rngData As Range
With sht
r = .Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
c = .Cells.Find("*", SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column
Set rngDB = .Range("a2", .Cells(r, c))
vDB = rngDB
End With
With sht1
Set rngData = .Range("b1", .Range("b" & Rows.Count).End(xlUp))
End With
'On Error Resume Next
For i = 1 To UBound(vDB, 1)
'If sht.Cells(i, 1).Value <> "" Then
If vDB(i, 1) <> "" Then
Set rng = rngData.Find(vDB(i, 1), LookIn:=xlValues, Lookat:=xlWhole)
If Not rng Is Nothing Then
'sht.Cells(i, ABCCodeCell).Value = sht1.Cells(rng.Row, 9).Value
vDB(i, ABCCodeCell) = rng.Offset(, 7)
'sht.Cells(i, 27).Value = sht1.Cells(rng.Row, 7).Value
vDB(i, 27) = rng.Offset(, 5)
'sht.Cells(i, 34).Value = sht1.Cells(rng.Row, 11).Value
vDB(i, 34) = rng.Offset(, 9)
End If
End If
Next
rngDB = vDB
End Sub