2015-07-27 10 views
5

Was ich habeeinen Wert aus einer Spalte finden und schnell die Zeilennummer der Zelle zurückkehren

ich für jeden Teil eine Datei mit Teilenummern und mehrere Lieferanten haben. Es gibt 1500 Teile mit jeweils etwa 20 möglichen Lieferanten. Der Einfachheit halber werden Teile in Spalte A aufgelistet, wobei jeder Lieferant danach eine Spalte belegt. Werte unter den Lieferanten werden manuell eingegeben, sind aber nicht wirklich wichtig.

In einem anderen Blatt habe ich eine Liste von Teilen, die aus einer Access-Datenbank importiert wird. Die Stückliste wird importiert, nicht jedoch die Lieferanteninfo. In beiden Fällen erscheint jeder Teil nur einmal.

Was will ich

ich einfach mal mit den Teilen in der importierten Liste tun, um die Lieferanten Informationen aus dem ersten Blatt passen. Im Moment habe ich eine Funktion, die jeden Teil der Liste mit Lieferanten durchgeht, die Lieferanteninformationen in ein Array kopiert, die Teilenummer in der importierten Teileliste findet (es gibt immer eine eindeutige Übereinstimmung) und das Array daneben kopiert (mit Lieferanteninfo innen). Es klappt. Leider wird die Suchfunktion bei jeder Verwendung erheblich verlangsamt. Ich weiß, dass es der Täter ist, durch verschiedene Tests, und ich kann nicht verstehen, warum es langsamer wird (beginnt bei 200 Wiederholungen pro Sekunde, verlangsamt sich auf 1 pro Sekunde und Excel stürzt ab). Vielleicht habe ich ein Leck? Die Dateigröße bleibt insgesamt 7mb. Hier ist sie:

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 

Die Funktion gibt einfach die Zeilennummer auf dem der Wert gefunden wird, oder 0, wenn es es nicht findet, was nie geschehen sollte.

Was muss ich mit

helfen Ich mag entweder würde die Ursache für die Verlangsamung, identifizieren oder einen Ersatz für die Find-Methode finden. Ich habe den Fund vorher benutzt und es ist das erste Mal, dass mir das passiert. Es wurde ursprünglich von der Website von Siddarth Rout übernommen: http://www.siddharthrout.com/2011/07/14/find-and-findnext-in-excel-vba/ Was seltsam ist, ist, dass es nicht startet langsam, es wird nur träge, wie es weiter geht.

Ich denke, mit Match könnte arbeiten, oder vielleicht dumping der Bereich zu suchen (die Teilenummern) in ein Array und versuchen, diese mit der Liste der importierten Teile Anzahl könnte funktionieren. Ich bin mir nicht sicher, wie es geht, aber meine Frage ist eher, welche schneller wäre (solange sie unter 15 Sekunden bleibt, ist es mir nicht wirklich wichtig, aber 1.500 Objekte 1500 Mal direkt aus dem Blatt zu schleifen ist Außer Frage). Würde jemand vorschlagen, über die Array-Lösung zu passen/verbringen mehr Stunden meinen Code zu beheben?

EDIT

Hier ist die Schleife aus aufgerufen wird. Ich glaube nicht, es ist problematisch:

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 

Wenn ich LigneAHNS = LigneNum durch LigneAHNS ersetzen = 20, beispielsweise der Code sehr schnell ausführt. Das Leck kommt daher von der Suchfunktion selbst.

+1

Hat überhaupt es hilft, die Linie 'Set oRange = Nothing' als letzte Zeile Ihrer Funktion hinzufügen? (Oder besser gesagt, bevor Sie 'Exit Function') –

+1

Was haben Sie um diese Funktion herum gebaut? Vielleicht ist das Problem die Schleife, von der Sie es anrufen? –

+0

Wie oft listen Sie Änderungen auf und haben Sie die Kontrolle darüber? Auch Sie sagen Schleifen Ich sehe keine Schleifen in Ihrem Code? –

Antwort

3

Eine andere Möglichkeit, es zu tun, ohne die Suchfunktion zu verwenden, könnte so etwas sein. Zuerst fügen Sie die Teil-IDs und ihre Zeilennummern in ein Skriptwörterbuch ein. Diese sind wirklich schnell zu suchen. Wie folgt aus:

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 

weiter zu optimieren, können Sie die Dict als öffentliche Variable deklarieren, füllen Sie es einmal, und es viele Male in Ihrem Lookups beziehen. Ich erwarte, dass dies schneller wäre, als ein cells.find bei jeder Suche über einen Bereich auszuführen.

zur Syntax der Elemente im Wörterbuch nachschlagen, finden Sie in Looping through a Scripting.Dictionary using index/item number

+0

Sehr cool Ich wollte jetzt schon eine Weile über die Wörterbücher lernen. Ich werde es ausprobieren und auf deine Antwort zurückkommen! –

+0

Ich fülle das Wörterbuch mit einem Array, weil ich mehrere Werte für jeden Schlüssel habe. Wenn Sie 1500 Einträge mit Arrays zu je 5 Strings füllen, dauert das Debugging für jedes Element in den Arrays etwa 6 Sekunden. Vielen Dank! Auch die gesamten 6 Sekunden sind nur wegen der debug.print, die Wörterbuchschleife selbst ist fast sofort! –

+0

Awesome, froh, ich könnte helfen. – CustodianOfCode

1

Sie könnten dies nur mit Excel-Zellenformeln und ohne VB erreichen, wenn Sie bereit sind, jedem Lieferanten auf Ihrem Hauptblatt Teile eine separate Spalte zu widmen. Sie können dann die bedingte Formatierung verwenden, um sie optisch ansprechender zu gestalten. Ich habe es mit 1500 Zeilen versucht und es ist sehr schnell.Die Erhöhung auf 5000 Zeilen wird merklich langsamer, aber du sagst, dass du nur 1500 Zeilen hast, also sollte es passend sein.

  • Auf Blatt 1, definieren einen Teil Nummernspalte und eine separate Spalte für jeden Lieferanten .
  • Erstellen Sie ein separates Blatt für jeden Lieferanten mit allen Teilenummern, die von diesem Lieferanten in Spalte A aufgeführt sind. Stellen Sie sicher, dass die Reihen der Lieferanten Blätter nach Teilenummer geordnet sind.
  • Namen jeder der Lieferanten Blätter gleich der zugehörigen Spalte auf Blatt 1.
  • Weisen die folgende Formel unter jeder Lieferanten Spaltenüberschrift auf Blatt 1 in jeder Zelle gezeigt LINIE:

    = NOT (ISNA (SVERWEIS ($ A2, INDIRECT (" '" & B $ 1 & "' A: A"), 1, FALSE)))

Der folgende Bildschirm Kappe zeigt dies umgesetzt alo ng mit der bedingten Formatierung zu markieren, welche Lieferanten haben, welche Teile:

enter image description here

Wenn Sie von Lieferanten verfügbaren Mengen zeigen wollten, dann haben Sie könnten immer eine zweite Säule (B) auf dem Anbieter Blätter enthalten letzte bekannte Mengen für jedes Teil und VLOOKUP verwenden, um Spalte B anstelle von A abzufragen.

+0

Danke für die Hilfe!Das hat aber nicht funktioniert, weil es im Arbeitsbuch eine Menge mehr gibt. Es gibt bereits 15 Blätter und es gibt rund 50 Endverbraucher. Die Lieferanteninformation kommt am Ende vieler anderer Informationen und sie muss leicht zu sehen sein, und es wird am Ende rund 7000 Teile mit 20 Lieferanten geben. Aber danke für deine Zeit! –

Verwandte Themen