Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
1584to1588
Aktuelles Verzeichnis
Verzeichnis Index
Übersicht Verzeichnisse
Vorheriger Thread
Rückwärts Blättern
Nächster Thread
Vorwärts blättern
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
Inhaltsverzeichnis

Code läuft extrem langsam

Code läuft extrem langsam
24.10.2017 13:37:26
Tobias
Hallo zusammen!
Ich habe auf der Arbeit seit einiger Zeit die Aufgabe, gewisse Dinge mit Excel zu programmieren und mich deshalb selber eingearbeitet. Nun stehe ich allerdings vor einem Problem, bei dem ich selber nicht wirklich weiterkomme.
Aus einer Listbox werden verschiedene Gesellschaften ausgewählt. Sobald auf "ok" geklickt wird, soll in Tabelle 1 in einer Spalte nach den in der Listbox ausgewählten Werten gesucht werden. Sofern der Wert in der Spalte mit dem in der Listbox ausgewählten Wert identisch ist, sollen gewisse Werte aus der Zeile ausgelesen und in Tabelle 2 geschrieben werden.
Da Tabelle 1 bis zu 3000 Zeilen hat, läuft die Schleife ewig. Daher meine Frage: Habt ihr Tipps, wie ich den Code beschleunigen kann? Gerne auch komplett andere Ansätze, die meinen Code ganz über den Haufen werfen.
Private Sub cmd_OK_Click()
Dim i As Integer
Dim k As Integer
Dim R As Integer
Dim Z As Integer
Dim ZeileMax As Integer
Dim ZeileMaxTab1 As Integer
Application.ScreenUpdating = False
With Tabelle2
'Bereich der ausgewählten Daten wird zunächst geleert
ZeileMax = .Cells(21, 2).End(xlDown).Row
.Range("B21:E" & ZeileMax).Clear
End With
'Daten der ausgewählten Einzelgesellschaften werden übernommen
k = 21
R = 1
ZeileMaxTab1 = Tabelle1.Cells(2, 3).End(xlDown).Row
For i = 0 To Me.List_EG.ListCount - 1
If Me.List_EG.Selected(i) = True Then
For Z = 2 To ZeileMaxTab1
If Tabelle1.Cells(Z, 3).Value = Me.List_EG.Column(0, i) Then
Tabelle2.Cells(k, 3).Value = Tabelle1.Cells(Z, 4).Value
Tabelle2.Cells(k, 4).Value = Tabelle1.Cells(Z, 5).Value
Tabelle2.Cells(k, 5).Value = Tabelle1.Cells(Z, 3).Value
Tabelle2.Cells(k, 2).Value = R
R = R + 1
k = k + 1
End If
Next Z
End If
Next i
Application.ScreenUpdating = True
'Dialogfeld wird geschlossen
Unload Me
End Sub

16
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: Code läuft extrem langsam
24.10.2017 13:50:57
Zwenn
Hallo Tobias,
Du benötigst einen schnelleren Suchalgorithmus. Dazu habe ich unter folgendem Link mal etwas geschrieben:
https://www.herber.de/cgi-bin/callthread.pl?index=1557784#1557863
Daniel hat im gleichen Thread etwas zur Umsetzung mit sverweis geschrieben und auch ein Code Beispiel veröffentlicht.
Vielleicht hilft Dir das als Ansatz weiter.
Viele Grüße,
Zwenn
AW: Code läuft extrem langsam
24.10.2017 15:35:37
Tobias
Vielleicht kann mir das jemand doch nochmal etwas kleinschrittiger darlegen, wie sowas funktionieren könnte. Wäre sehr dankbar dafür!
Anzeige
AW: Code läuft extrem langsam
24.10.2017 13:57:45
Tobias
Ja, sorry dafür! Hab's im anderen Forum nun geschlossen.
Er läuft schleppend. Habe den Code mal über die Mittagspause laufen lassen... dachte bisher immer, der PC sei abgestürzt. ;)
ich lese mich mal in den Post von zwenn ein und melde mich dann wieder!
VG
Anzeige
AW: Code läuft extrem langsam
24.10.2017 14:57:47
Tobias
Ich muss doch nochmal nachhaken...
neuer Ansatz: Ich habe nun ein Array definiert, das alle ausgewählten Elemente der Listbox in sich sammelt. Auch die S-Verweis-Funktionen habe ich schonmal niedergeschrieben.
Irgendwie muss ich es jetzt noch schaffen, dass er mir nun alle Zeilen, in denen die ausgewählten Werte gefunden wurden (ein Wert kann in Spalte mehrfach vorkommen) ausliest und woanders hinkopiert. Wie stelle ich das am besten an?
Mein Problem ist, dass ich nicht weiß, wie ich nun mit den S-Verweisen weiter verfahren. Sie müssten mir ja an sich alle anderen Werte in der Zeile, in der der Wert aus der LIstbox gefunden wurde, wiedergeben können!?
Private Sub cmd_OK_Click()
Dim a As Integer
Dim i As Integer
Dim b As Integer
Dim c As Integer
Dim ZeileMax As Integer
Dim ZeileMaxTab1 As Integer
Dim arrCriteria() As String
Application.ScreenUpdating = False
With Tabelle2
'Bereich der ausgewählten Risiken wird zunächst geleert
ZeileMax = .Cells(21, 2).End(xlDown).Row
.Range("B21:E" & ZeileMax).Clear
End With
'Bestimmung der Dimensionalität des Arrays mit der Anzahl der ausgewählten EGs in Listbox
a = 0
For i = 0 To Me.List_EG.ListCount - 1
If Me.List_EG.Selected(i) = True Then a = a + 1
Next i
'Re-Dimensionierung des Arrays
ReDim arrFilterCriteria(0 To a)
'Befüllen des Arrays mit den ausgewählten Einzelgesellschaften
c = 0
For b = 0 To a
arrCriteria(b) = Me.List_EG.Column(0, c)
c = c + 1
Next b
ID = WorksheetFunction.VLookup(arrCriteria, Tabelle1.Range("C2:E" & ZeileMaxTab1), 2, False) _
Risiko = WorksheetFunction.VLookup(arrCriteria, Tabelle1.Range("C2:E" & ZeileMaxTab1), 3,  _
False)
Org = WorksheetFunction.VLookup(arrCriteria, Tabelle1.Range("C2:E" & ZeileMaxTab1), 1,  _
False)
Application.ScreenUpdating = True
'Dialogfeld wird geschlossen
Unload Me
End Sub

Anzeige
AW: Code läuft extrem langsam
24.10.2017 16:31:26
Nepumuk
Hallo Tobias,
teste mal:
Private Sub cmd_OK_Click()
    
    Dim i As Long
    Dim k As Long
    Dim R As Long
    Dim ZeileMax As Long
    Dim objCell As Range
    Dim strFirstAddress As String
    
    With Application
        .Calculation = xlCalculationManual
        .EnableEvents = False
        .ScreenUpdating = False
    End With
    
    With Tabelle2
        'Bereich der ausgewählten Daten wird zunächst geleert
        ZeileMax = .Cells(.Rows.Count, 2).End(xlUp).Row
        .Range("B21:E" & CStr(ZeileMax)).Clear
    End With
    
    'Daten der ausgewählten Einzelgesellschaften werden übernommen
    k = 21
    R = 1
    
    For i = 0 To List_EG.ListCount - 1
        
        If List_EG.Selected(i) Then
            
            Set objCell = Tabelle1.Columns(3).Find(What:=List_EG.Column(0, i), _
                After:=Tabelle1.Cells(1, 3), LookIn:=xlValues, LookAt:=xlWhole, MatchCase:=True)
            If Not objCell Is Nothing Then
                strFirstAddress = objCell.Address
                Do
                    Tabelle2.Cells(k, 3).Value = objCell.Offset(0, 1).Value
                    Tabelle2.Cells(k, 4).Value = objCell.Offset(0, 2).Value
                    Tabelle2.Cells(k, 5).Value = objCell.Value
                    Tabelle2.Cells(k, 2).Value = R
                    R = R + 1
                    k = k + 1
                    Set objCell = Tabelle1.Columns(3).FindNext(After:=objCell)
                Loop Until objCell.Address = strFirstAddress
                Set objCell = Nothing
            End If
        End If
    Next i
    
    With Application
        .Calculation = xlCalculationAutomatic
        .EnableEvents = True
        .ScreenUpdating = True
    End With
    
    'Dialogfeld wird geschlossen
    Unload Me
    
End Sub

Gruß
Nepumuk
Anzeige
AW: Code läuft extrem langsam
24.10.2017 16:51:25
Tobias
Krass... das funktioniert und dazu auch noch wahnsinnig schnell! Vielen Dank für die tolle Hilfe!
Ich habe soeben noch einen ganz anderen Ansatz entdeckt. Indem ich alle ausgewählte Listbox-Elemente in einen Array geschrieben habe und dann die Tabelle 1 danach gefiltert habe, konnte ich auch deutlich schneller als bei meinem ersten Ansatz kopieren. Ging auch gut...
Nichtsdestotrotz ist Ihr Ansatz nochmal um einiges schneller. Dafür nochmal meinen ausdrücklichsten Dank! Bin etwas überwältigt, wie schnell man solche Probleme offensichtlich lösen kann, wenn man Profi ist. ;)
VG!
AW: Code läuft extrem langsam
24.10.2017 16:35:21
onur
Kannst du mal die Datei posten?
Anzeige
AW: Code läuft extrem langsam
24.10.2017 16:48:54
Tobias
Leider nein... Datenschutz ;)
AW: Code läuft extrem langsam
24.10.2017 16:49:58
onur
Kannst du anonymisieren, mich interessieren deine Daten nicht.
AW: Code läuft extrem langsam
24.10.2017 16:52:37
Tobias
Vielen Dank für das Angebot! Allerdings funktioniert der Code von Nepumuk schon super! Vielen Dank nochmals!
AW: noch ne Variante
24.10.2017 17:30:27
Daniel
Hi
test mal das, das dürfte auch recht schnell sein (ich habe es nicht getestet):

Sub test()
Dim txt As String
Dim ZeileMax As Long
'--- alten Inhalt löschen
With Tabelle2
.Range("B21:E" & .Cells(21, 2).End(xlDown).Row).Clear
End With
'--- zu selektierende Daten ermitteln
For i = 0 To Me.List_EG.ListCount - 1
If Me.List_EG.Selected(i) Then
txt = txt & "|" & Me.List_EG.List.Column(0, i)
End If
Next
txt = txt & "|"
'--- Daten auswählen und einfügen
With Tabelle1.UsedRange
With .Columns(.Columns.Count + 1)
.FormulaR1C1 = "=IF(ISNUMBER(FIND(""|""&RC3&""|"",""" & txt & """)),1,"""")"
.Formula = .Value
If WorksheetFunction.Sum(.Cells) > 0 Then
With .SpecialCells(xlCellTypeConstants, 1)
Intersect(.EntireRow, .Worksheet.Range("D:E")).Copy
Tabelle2.Cells(21, 3).PasteSpecial xlPasteValues
Intersect(.EntireRow, .Worksheet.Range("C:C")).Copy
Tabelle2.Cells(21, 5).PasteSpecial xlPasteValues
End With
End If
.ClearContents
End With
End With
'--- Reihenfolgennummer einfügen
With Tabelle2
.Cells(21, 2).Value = 1
.Range(.Cells(21, 2), .Cells(.Rows.Count, 3).End(xlUp).Offset(0, -1)).DataSeries _
Rowcol:=xlColumns, _
Type:=xlLinear, _
Step:=1
End With
End Sub
sollte das immer noch nicht schnell genug sein, könnte man die Liste vor dem Kopieren noch nach der Hilfsspalte sortieren, so dass die zu kopierenden Werte Lückenlos bei einander stehen.
Gruß Daniel
Anzeige
AW: noch ne Variante
24.10.2017 17:34:34
Tobias
Wow! Vielen Dank auch Dir!
AW: nur so fürs persönliche Ego...
24.10.2017 17:55:31
Daniel
... da du jetzt verschiedene Lösungswege ausprobiert hast, kannst du sagen, die Laufzeiten mit deiner Datenmenge so im Vergleich liegen?
Ich muss ja wissen, ob ich bei meinem Ansatz bleiben kann oder mir die anderen Lösungen mal genauer anschauen sollte.
Gruß Daniel
AW: nur so fürs persönliche Ego...
24.10.2017 18:03:56
Tobias
Aber klar doch!
Bei dem Ausruck
txt = txt & "|" & Me.List_EG.List.Column(0, i)
tritt Lfz-Fehler zum Debuggen auf. Vielleicht hilft das erstmal!? Sorry, ganz so bewandert, dass ich das in Null Komma Nichts beheben kann, bin ich leider nicht.
Ich bin jetzt gleich auch im Feierabend. Würde evtl. am Donnerstag nochmal nachgucken, wenn ich wieder im Büro bin. ;) Morgen sitze ich leider von früh bis spät in der Uni.
Anzeige
AW: nur so fürs persönliche Ego...
24.10.2017 18:30:26
Daniel
Hi
da liegt der Fehler wohl bei dir, wie du die Listbox ansprichst.
das hatte ich von dir übernommen, da ich das mangels Beispieldatei von dir nicht testen konnte.
der Fehler dürfte wohl darin liegen, wie du die Daten aus der Listbox holst, vielleicht ist es auch ein einfacher Tippfehler von mir (wie gesagt, ohne deine Beispieldatei kann ich sowas nicht prüfen)
Im prinzip werden hier alle ausgewählten Elemente aus der Listbox zu einem einzigen Textstring mit dem Trennzeichen "|" zusammengesetzt.
ich hätte das normalerweise so programmiert:
Einspaltige Listbox:
txt = txt & "|" & Me.List_EG.List(i)

Mehrspaltige Listbox:
txt = txt & "|" & Me.List_EG.List(i, 0) 'hier ggf die Spaltennummer anpassen

hatte dann aber den Code von dir übernommen.
Gruß Daniel
Anzeige

Links zu Excel-Dialogen

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige