0

我有 2 个文件。当用户运行宏时已经打开的第一个文件有 5 个工作表。每个工作表在不同的位置包含一个“订单项”列。示例工作表看起来像这样

-Date Time Order-item Order-Quanity 
-1020 9:30 item533333 (blank)
-1020 7:30 item733333 (blank)
-1020 2:30 item333332 (blank)
-1020 6:30 item121242 (blank)

运行宏后,用户将选择要打开的文件,如下所示:

-Order-item Order-Quantity
-item121242 183
-item333332 515
-item533333 27
-item333332 761

然后,宏会遍历原始文件中的每个工作表。在每个工作表上,它会找到 order-item 列所在的位置,然后遍历列上的每个项目。它在用户选择的文件中搜索订单项目(通常是 A 列)并查找数量(总是与订单项目列相邻,在这种情况下是 B 列)

运行原始工作表后应如下所示:

-Date Time Order-item Order-Quanity
-1020 9:30 item533333 27
-1020 7:30 item733333 515 
-1020 2:30 item333332 761
-1020 6:30 item121242 183

我创建了一个宏来执行此操作,但由于两个文件都相当大(原始文件有大约 10,000 行,而用户打开的文件有多达 50,000 行),我的宏需要一些时间来执行。我意识到我可以简单地做一个 Vlookup,filldown,然后粘贴值,它会快得多;但是,这是更大的自动化宏的一部分,这是不可行的。是否有人可以提出任何改进建议以使我的代码运行得更高效或更快?如果是这样,请告诉我。谢谢!

Public Sub OpenFile()

Dim FilePath As Variant
Dim FileName As String
Dim CurrentWorkbook As String
Dim thisWB As Workbook
Dim openWB As Workbook
Dim sh As Worksheet
Dim lastRow As Long
Dim myRange As Range
Dim FoundCell As Range
Dim counter1 As Long
Dim counter2 As Long
Dim orderColumn As Long

Set thisWB = Application.ActiveWorkbook
CurrentWorkbook = Application.ActiveWorkbook.Name
FilePath = Application.GetOpenFilename(FileFilter:= _
            "Excel Workbook Files(*.xl*),*.xl*", MultiSelect:=False, Title:="Select File")
If Not FilePath = False Then
    FileName = FilePath
    Set openWB = Application.Workbooks.Open(FileName)
    FileName = Mid(FileName, InStrRev(FileName, "\") + 1, Len(FileName)) 'extracts filename from path+filename
Else
    MsgBox ("File not selected or selected file not valid")
    Exit Sub
End If
Application.Workbooks(FileName).Activate
'--------------------------------------------------------------------------------------------------
'--------------gets table range from input box.  Defailt is Row A,B--------------------------------
'--------------------------------------------------------------------------------------------------
Set myRange = Application.InputBox( _
    "Select Table Range.  First Column should be Order-item, Second Column should be Order Grade", _
    "Select Range", "$A:$B", , , , , 8)
On Error GoTo 0
'for every worksheet in currentworkbook, find how many rows there are.and find location of _
order-item. then go through each row in the order-item column and compare to column A(order-item) _
on the user selected workbook.  if match is found, place column B into order-item column+1
Application.ScreenUpdating = False
For Each sh In thisWB.Worksheets
    lastRow = LastRowUsed(sh)
    'Find Order Column
    Set FoundCell = sh.Rows(1).Find(what:="Order-Item", LookIn:=xlValues, _
    LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
    MatchCase:=False, SearchFormat:=False)
    If Not FoundCell Is Nothing Then
        orderColumn = FoundCell.Column
    Else
        MsgBox ("Couldn't find ""Order-Item"" in Header, exiting macro")
        Exit Sub
    End If

    For counter1 = lastRow To 1 Step -1
        For counter2 = myRange.Rows.Count To 1 Step -1
        If sh.Cells(counter1, orderColumn) = myRange.Cells(counter2, 1).Value Then
            sh.Cells(counter1, orderColumn + 1) = myRange.Cells(counter2, 2)
            Exit For
        End If
        Next
    Next
Next
Application.ScreenUpdating = True
End Sub
4

2 回答 2

1

你为什么不让你的 VBA 使用 Application.worksheetFunction.VLOOKUP ?

于 2013-10-27T20:34:15.430 回答
0

编辑:更新以处理重复的 ID。

Sub Tester()
    UpdateFromSelection Workbooks("Book3").Sheets("Sheet1").Range("A1:B21")
End Sub

Sub UpdateFromSelection(myRange As Range)
    Dim d, rw As Range, tmp, c As Range, arr, i

    Set d = GetItemMap()

    If d Is Nothing Then Exit Sub
    Debug.Print d.Count
    If d.Count = 0 Then
        MsgBox "nothing found!"
        Exit Sub
    End If

    For Each rw In myRange.Rows
        tmp = rw.Cells(1).Value
        If Len(tmp) > 0 Then
        If d.exists(tmp) Then
            arr = d(tmp)
            For i = LBound(arr) To UBound(arr)
                arr(i).Value = rw.Cells(2).Value
            Next i
        End If
        End If
    Next rw

End Sub

Function GetItemMap() As Object
Dim dict As Object, ws As Worksheet
Dim f As Range, lastRow As Long, tmp, arr, ub As Long

    Set dict = CreateObject("scripting.dictionary")
    For Each ws In ThisWorkbook.Worksheets
        Set f = ws.Rows(1).Find(what:="Order-Item", LookIn:=xlValues, _
                                LookAt:=xlWhole)
        If Not f Is Nothing Then
            Set f = f.Offset(1, 0)
            lastRow = ws.Cells(Rows.Count, f.Column).End(xlUp).Row
            Do While f.Row <= lastRow
                tmp = Trim(f.Value)
                If Len(tmp) > 0 Then
                    If Not dict.exists(tmp) Then
                        dict.Add tmp, Array(f.Offset(0, 1))
                    Else
                        'can same item# exist > once?
                        arr = dict(tmp)
                        ub = UBound(arr) + 1
                        ReDim Preserve arr(0 To ub)
                        Set arr(ub) = f.Offset(0, 1)
                        dict(tmp) = arr
                    End If
                End If
                Set f = f.Offset(1, 0)
            Loop
        Else
            MsgBox ("Couldn't find 'Order-Item' in Header!")
            Exit Function
        End If
    Next ws

    Set GetItemMap = dict
End Function
于 2013-10-27T21:07:08.957 回答