2017-08-01 117 views
0

我正在研究一個由一系列表格和幾個宏組成的大型項目。我需要逐月更新的主要報告是21K行,並在不斷增長。它在12個獨立的專欄中收集所有12個月的更新。要完成「更新」,我必須匹配包含在列「A」中的主文件中的部件號(21k行是所有部件號及其信息),並將其與部件號生成的另一報告相匹配(此時包含在柱9 sht1的代替Vlookup找到大20k行表嗎?

地點的值由變量

地點指定列7 sht1的值設置爲SHT柱:柱「B」),並且如果它匹配(需要被精確匹配),下面的返回SHT柱27

地點塔11 SHT 1至SHT柱34

每次匹配時

的值,由RO循環排w,直到列A中包含的最後一個零件編號在sht中。

下面的代碼有效,但我想知道是否有更好的方法我應該寫這個?這對於處理速度和準確性來說是最好的嗎?我剛剛在另一個代碼塊中意識到,這種方法沒有執行完全匹配,現在已經拋出了一面紅旗,可能會改變我的方法。我絕對需要這樣做是準確的,它必須完全匹配,或者將內容留空。

'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

@Tim Williams就是這樣。我只是不得不重寫它,因爲我之前發佈過它,但沒有人回覆,所以我在幾天後刪除了它。謝謝! - 雅典娜,又名SharePoint0508 – SharePoint0508

+3

它對我來說看起來不錯...目前它運行速度太慢嗎?你是否在使用'Application.ScreenUpdating = False,Application.Cursor = xlWait'等等?有什麼特別不起作用?這對Code Review來說可能是一個更好的問題。 – dwirony

+0

*我剛剛在另一個代碼塊中實現,這種方法沒有執行完全匹配,*,這是什麼意思? – dwirony

回答

1

我不會在你的代碼是否是速度等最佳的代碼註釋,因爲這是不是真的對話題的堆棧溢出 - 這些類型的問題應該在Code Review詢問。

我會然而答案再你的「(必須是精確匹配)」的評論:

的Excel允許用戶指定各種選項進行查找時:

enter image description here

大多數(所有? )這些選項在下一次查找時會被記住並默認使用,可以是由用戶執行的手動查找,也可以是VBA代碼中已編程的Find

您當前的發現(sht1.Range("B:B").Find(sht.Cells(i, 1).value))不指定除What參數以外的任何參數,因此會使用任何用戶上次使用的LookInLookAtMatchCase參數的值。

如果您想執行完全匹配,並且您不相信用戶在運行代碼之前沒有完成部分匹配,則應明確指出您希望使用的選項。

我建議你改變你的Find是:

Set rng = sht1.Range("B:B").Find(What:=sht.Cells(i, 1).Value, _ 
           LookIn:=xlValues, _ 
           LookAt:=xlWhole, _ 
           MatchCase:=True) 
1

在大循環中運行Find()是相當緩慢相比,使用Match()

例如,在20000的不同值的列中查找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 
+0

如果您首先將搜索範圍讀入數組,那麼匹配會更快嗎? – YowE3K

+0

嗯 - 看起來不是 - 我得到14.32的查找,1.11匹配和13.06匹配數組(與時間讀取到數組顯示爲0) – YowE3K

+0

@ YowE3K - 匹配更快(約10倍)反對工作表比數組(編輯:你已經想出了) –

0

如果SHT尚未式電池,使用變量數組更快。

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