Vba 从列中查找值并快速返回其单元格的行号

Vba 从列中查找值并快速返回其单元格的行号,vba,excel,Vba,Excel,我拥有的 我有一个文件,上面有零件号,每个零件有几个供应商。有1500个零件,每个零件大约有20个可能的供应商。为了简单起见,假设零件列在A列中,每个供应商在A列之后占据一列。供应商项下的值是手动输入的,但实际上并不重要 在另一张表中,我有一个从Access数据库导入的零件列表。将导入明细表,但不导入供应商信息。在这两种情况下,每个零件仅显示一次 我想做什么 我只是想将第一张表中的供应商信息与导入列表中的零件进行匹配。现在,我有一个函数,它与供应商一起遍历列表中的每个零件,将供应商信息复制到一个

我拥有的

我有一个文件,上面有零件号,每个零件有几个供应商。有1500个零件,每个零件大约有20个可能的供应商。为了简单起见,假设零件列在A列中,每个供应商在A列之后占据一列。供应商项下的值是手动输入的,但实际上并不重要

在另一张表中,我有一个从Access数据库导入的零件列表。将导入明细表,但不导入供应商信息。在这两种情况下,每个零件仅显示一次

我想做什么

我只是想将第一张表中的供应商信息与导入列表中的零件进行匹配。现在,我有一个函数,它与供应商一起遍历列表中的每个零件,将供应商信息复制到一个数组中,在导入的零件列表中查找零件号(始终存在唯一匹配项),并复制其旁边的数组(其中包含供应商信息)。它起作用了。不幸的是,每次使用find函数时,它的速度都会大大降低。通过各种测试,我知道这是罪魁祸首,但我不理解它为什么会减慢(从每秒200次循环迭代开始,减慢到每秒1次,Excel崩溃)。我可能有点泄密?文件大小始终保持为7mb。这是:

Function LigneNum(numAHNS As String) As Integer
    Dim oRange As Range, aCell As Range
    Dim SearchString As String

    Set oRange = f_TableMatrice.Range("A1:A1500")
    SearchString = numAHNS

    Set aCell = oRange.Find(What:=SearchString, LookIn:=xlValues, _
        LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
        MatchCase:=False, SearchFormat:=False)

    If Not aCell Is Nothing Then
        'We have found the number by now:
            LigneNum = aCell.Row
        Exit Function
    Else
        MsgBox "Un numéro AHNS n'a pas été trouvé: " & SearchString
        Debug.Print SearchString & " not found!"
            LigneNum = 0
        Exit Function
    End If

End Function
该函数只返回找到该值的行号,如果找不到,则返回0,这是不应该发生的

我需要什么帮助

我想找出速度减慢的原因,或者找到find方法的替代方法。我以前用过这个发现,这是第一次发生在我身上。它最初是从Siddarth Rout的网站上获得的:奇怪的是,它的启动速度并不慢,只是随着时间的推移变得缓慢

我认为使用Match可以工作,或者将搜索范围(零件号)转储到一个数组中,并尝试将其与导入的零件号列表匹配也可以工作。我不知道怎么做,但我的问题更多的是关于哪一个会更快(只要它保持在15秒以下,我并不在乎,但是,在工作表上循环1500个项目1500次是不可能的)。是否有人建议使用阵列匹配解决方案/花更多时间修复我的代码

编辑

这是从中调用它的循环。我不认为这是有问题的:

For Each cellToMatch In rngToMatch
        Debug.Print cellToMatch.Row
        'The cellsToMatch's values are the numbers I want, rngToMatch is the column where they are.

        For i = 2 To nbSup + 1
            infoSup(i - 2) = f_TableMatrice.Cells(cellToMatch.Row, i)
        Next
        'infoSup contains the required supplier data now
        'I call the find function here to find the row where the number appears in the imported sheet
        'To copy the array nbSup on that line
        LigneAHNS = LigneNum(cellToMatch.Value) 'This is the Find function
        If LigneAHNS = 0 Then Exit Sub
        'This loop just empties the array in the right line.
        For i = LBound(infoSup) To UBound(infoSup)
            f_symix.Cells(LigneAHNS, debutsuppliers + i) = infoSup(i)
        Next

    Next

例如,如果我将LigneAHNS=LigneNum替换为LigneAHNS=20,代码执行速度会非常快。因此,泄漏源于find函数本身。

如果您愿意在主要零件表上为每个供应商单独列出一列,则可以仅使用Excel单元格公式而不使用VB来实现这一点。然后,您可以使用条件格式使其在视觉上更具吸引力。我试过1500排,速度很快。将它增加到5000行会明显变慢,但是您说现在只有1500行,所以它应该是合适的

  • 在表1中,为每个供应商定义一个零件号列和一个单独的列

  • 为每个供应商创建一张单独的表格,表格a列中列出了该供应商提供的所有零件号。确保供应商表格上的行按零件号排序

  • 将每个供应商表命名为与表1所示的相关列标题相同的名称

  • 在第1页每个供应商栏标题下的每个单元格中指定以下公式:

    =NOT(ISNA(VLOOKUP($A2,间接(““”&B$1&“!A:A”),1,FALSE)))

以下屏幕封口显示了此功能以及条件格式,以突出显示哪些供应商拥有哪些零件:


如果您想显示供应商提供的数量,那么您可以在供应商表上设置第二列(B),其中包含每个零件的最后已知数量,并使用
VLOOKUP
检索B列,而不是a列。

不使用查找功能的另一种方法可能是这样的。首先,将部件ID及其行号放入脚本字典中。这些都是非常快速的查找。像这样:

Dim Dict As New Scripting.Dictionary
Dim ColA As Variant
Lastrow=range("A50000").end(xlUp).Row
ColA = Range("A1:A" & LastRow).Value
For i = 1 To LastRow
    Dict.Add ColA(i, 1), i
Next i
为了进一步优化,您可以将Dict声明为公共变量,填充一次,并在查找中多次引用它。我希望这比每次查找时运行cells.find都要快


有关在字典中查找项目的语法,请参阅

将行
设置为oRange=Nothing
作为函数的最后一行是否有帮助?(或者更确切地说,在您退出函数之前)您围绕该函数构建了什么?也许问题在于你调用它的循环?你多久列出一次更改?你有控制权吗?你还说循环我在你的代码中没有看到循环?我和莫里茨在一起。你没有需要很长时间的循环。它可能是基于它正在搜索的列表的查找。调用此函数的代码是什么?您可以发布调用过程吗?我同意MoritzSchmitzv.Hülst和MatthewD的观点,问题更可能出在您的呼叫过程中。这段代码本身似乎没有任何问题会导致您所描述的速度减慢。非常酷,我一直想学习词汇。我会试试看,然后回到你的答案上来!我用数组填充字典,因为每个键都有几个值。用5个字符串的数组填充1500个条目,然后进行调试。打印数组中的每个条目大约需要6秒钟。非常感谢你!另外,整个6秒钟都是因为debug.print,单词循环本身几乎是瞬时的!太棒了,很高兴我能帮忙。谢谢你的帮助!不过,这是行不通的,因为工作簿中还有很多事情要做。已经有15个了