Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
980to984
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
980to984
980to984
Aktuelles Verzeichnis
Verzeichnis Index
Verzeichnis Index
Übersicht Verzeichnisse
Inhaltsverzeichnis

VBA-Code optimieren

VBA-Code optimieren
03.06.2008 20:18:38
Konni
Hallo Freaks,
nachstehenden VBA-Code habe ich am 02.06. zu Lösungsvorschlägen schon einmal eingestellt. Leider habe ich bis jetzt keine Antwort bekommen. Vielleicht kann mir jetzt jemand helfen!?
Das Problem ist, dass die Ausführung des Makros zu lange dauert und die "Eieruhr" währenddessen flackert. - Kurzum, das Ganze soll schneller ablaufen! (Dieser Code wurde von mir mit Forumshilfe zusammengebastelt", da ich nur sehr beschränkte VBA-Kenntnisse besitze!)

Sub Doppeleinträge_aus_Spalten_löschen()
ScreenUpdating = False
Dim r, c As Variant
With Range("AP19:AP1018").Select
Set r = Selection.Cells
For c = r.Cells.Count To 1 Step -1
If Application.CountIf(r, r(c))  1 Then r(c).Value = ""
Next c
End With
With Range("AQ19:AQ1018").Select
Set r = Selection.Cells
For c = r.Cells.Count To 1 Step -1
If Application.CountIf(r, r(c))  1 Then r(c).Value = ""
Next c
End With
With Range("AR19:AR1018").Select
Set r = Selection.Cells
For c = r.Cells.Count To 1 Step -1
If Application.CountIf(r, r(c))  1 Then r(c).Value = ""
Next c
End With
With Range("AS19:AS1018").Select
Set r = Selection.Cells
For c = r.Cells.Count To 1 Step -1
If Application.CountIf(r, r(c))  1 Then r(c).Value = ""
Next c
End With
With Range("AT19:AT1018").Select
Set r = Selection.Cells
For c = r.Cells.Count To 1 Step -1
If Application.CountIf(r, r(c))  1 Then r(c).Value = ""
Next c
With Range("AU19:AU1018").Select
Set r = Selection.Cells
For c = r.Cells.Count To 1 Step -1
If Application.CountIf(r, r(c))  1 Then r(c).Value = ""
Next c
End With
With Range("AV19:AV1018").Select
Set r = Selection.Cells
For c = r.Cells.Count To 1 Step -1
If Application.CountIf(r, r(c))  1 Then r(c).Value = ""
Next c
End With
With Range("AW19:AW1018").Select
Set r = Selection.Cells
For c = r.Cells.Count To 1 Step -1
If Application.CountIf(r, r(c))  1 Then r(c).Value = ""
Next c
End With
End With
Application.CutCopyMode = False
Range("O19").Select
ScreenUpdating = True
End Sub


Vielen Dank für Eure Unterstützung!
Gruß: Konni

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

Betreff
Datum
Anwender
Anzeige
AW: VBA-Code optimieren
03.06.2008 20:56:45
Daniel
Hi
  • du arbeitest überflüssigerweise mit SELECT, was den Code langsam macht.

  • statt
    
    Range("AV19:AV1018").Select
    Set r = Selection.Cells
    


    kann man auch gleich direkt schreiben:

    
    Set r = Range("AV19:AV1018")
    


  • deklariere Variablen so, wie sie auch verwendet werden und nicht grundsätzlich als Variant

  • in deinem Beispiel also:
    
    dim r as Range
    dim c as Long
    


  • du setzt das Prinzip der WITH-Klammer falsch ein

  • ne With-Klammer wird verwendet, um Schreibarbeit zu sparen, da das im WITH-Teil festgelegte Objekt im folgenden durch einen Punkt ersetzt werden kann. Beispiel:
    
    WITH Range("A1:C10")
    .value = "xxx"
    .interior.Colorindex = 10
    end with
    


    in deinem Code brauchst die WITH-Klammer nicht, da du ja mit Variablen arbeitest.

  • Range-Schreibweise

  • alternativ zu der von dir verwendeten RANGE-Schreibweise für einen Zellbereich kann man auch CELLS verwenden , also stelle von:
    
    Range("AP19:AP1018")
    


    kann man auch Schreiben:

    
    Range(Cells(19, 42), Cells(1018, 42))
    


    da hier auch die Spalten durch Zahlen beschrieben werden und so durch Variablen ersetzt werden können, kannst du deinen Code durch ne weitere Schleife für die einzelnen Spalten zwar nicht beschleunigen, aber stark verkürzen, da für jede Spalte ja gleichen Befehle ablaufen.

  • der Zeitfresser in deinem Code ist die CountIF-Funktion

  • erschwerden kommt hinzu, daß du immer den vollen Zellbereich von r verwendest.
    das ist aber nicht notwendig, da der Zellbereich mit dem Schleifendurchlauf verkleinert werden kann, da der untere Bereich (unterhalb der Zelle r(c) ) ja "bereinigt" ist.
    etwas schneller dürfte also folgende Formel sein:
    
    For c = r.Cells.Count To 1 Step -1
    If Application.CountIf(Range(r(1), r(c)), r(c))  1 Then r(c).Value = ""
    Next c
    


    weil hier nur der notwendige Teil von r in der Prüfung verwendet wird.
    weitere Beschleunigungmethoden dürften deinen Kenntnisstand vorerst noch übersteigen, oder sie erfordern eine genauere Kenntnist der Daten.
    Beispielsweise ließe sich das ganze beschleunigen, wenn die Daten einzelen sortiert werden könnten, weil dann zum Finden der doppelten nur zwei benachbarte Zellen geprüft werden müssen.
    Bei CountIf werden hingegen ALLE Zellen mit dem Wert verglichen, was natürlich deutlich länger dauert.
    Gruß, Daniel

    Anzeige
    AW: VBA-Code optimieren (o.T.)
    04.06.2008 01:46:00
    Gerhard
    wow Daniel, danke!!!
    nun habe auch ich "Newbie" wieder was gelernt und dein Beitrag ist kopiert und abgespeichert...
    Klar steht das was du geschrieben hast in vielen Büchern, aber so kurz, knackig ohne viele überflüssige Abschweifungen und trotzdem verständlich, da mit Beispielen, sucht man vergebens!!!
    DANKE *verneig*
    Gruß Gerhard

    AW: VBA-Code optimieren
    05.06.2008 11:08:29
    Konni
    Hallo Daniel,
    leider kann ich erst jetzt antworten, da meine Grafikkarte ihren Geist aufgegeben hatte (nach 6 Jahren war Schluss).
    Anerkennend bewerte ich Deine Rückmeldung und habe Deine Hinweise ebenfalls abgespeichert. - Mit VBA stehe ich auf dem Kriegsfuß, aber vielleicht bleibt von Deinen ausführlichen Erklärungen doch etwas in meinem Kopf hängen.
    Vielen Dank und Gruß: Konni

    Anzeige
    AW: VBA-Code optimieren
    03.06.2008 21:01:00
    Uduuh
    Hallo,
    versuch mal:
    
    Sub Doppeleinträge_aus_Spalten_löschen()
    Application.ScreenUpdating = False
    Dim r As Range, c As Range, iCol As Integer, rDel As Range
    For iCol = 42 To 49
    Set r = Range(Cells(19, iCol), Cells(1018, iCol))
    For Each c In r
    If Application.CountIf(Range(r(1), c), c) > 1 Then
    If rDel Is Nothing Then
    Set rDel = c
    Else
    Set rDel = Union(rDel, c)
    End If
    End If
    Next c
    Next iCol
    rDel = ""
    Application.ScreenUpdating = True
    End Sub
    


    Gruß aus’m Pott
    Udo

    AW: VBA-Code optimieren
    03.06.2008 21:36:04
    Gerd
    Hallo Konny,
    so geht' s auch.
    
    Sub Doppeleinträge_aus_Spalten_löschen3()
    Dim row As Long, col As Long
    Application.ScreenUpdating = False
    With ThisWorkbook.Worksheets("Tabelle1") 'ANPASSEN !
    For col = 42 To 49
    For row = 1018 To 20 Step -1
    If Application.CountIf(.Range(.Cells(row, col), _
    .Cells(19, col)), .Cells(row, col).Value) > 1 Then .Cells(row, col).Value = ""
    Next row
    Next col
    End With
    Application.ScreenUpdating = True
    End Sub
    


    Gruß Gerd

    Anzeige
    @Udo und Gerd
    05.06.2008 11:24:00
    Konni
    Hallo Ihr beiden,
    leider kann ich mich jetzt erst melden, da meine Grafikkarte ihren Geist aufgegeben hatte. Inzwischen habe ich eine neue drin, sonst könnte ich Euch ja nicht anworten ;-) !
    Nun zu Euren Codes; sie funktionieren einwandfrei, unter der Voraussetzung, dass in jeder Spalte (bei mir 42-49) ein Eintrag vorhanden ist.
    Dies ist jedoch nicht immer der Fall. Es kommt vor, dass nur in Spalte 49 Einträge vorhanden sind (oder in einer anderen Spalte). Wenn dies der Fall ist, so erscheint die Fehlermeldung "Typen unverträglich".
    Wenn ich den Code auf die betreffende Spalte eingrenze, so klappt alles wunderbar.
    Was muss an den Codes geändert werden, damit sie leere Spalten ignorieren und nur die Spalten mit Inhalten auswerten?
    Vielen Dank für Eure Unterstützung!!
    Viele Grüße: Konni

    Anzeige
    AW: Doppelte Einträge - Zeile löschen
    05.06.2008 20:30:00
    Gerd
    Hallo Konni,
    so besser ?
    
    Sub Doppeleinträge_aus_Spalten_löschen3A()
    Dim row As Long, col As Long
    Application.ScreenUpdating = False
    With ThisWorkbook.Worksheets("Tabelle1") 'ANPASSEN !
    For col = 42 To 49
    If Application.WorksheetFunction.CountA(.Range(.Cells(19, col), .Cells(1018, col))) > 0  _
    Then
    For row = 1018 To 20 Step -1
    If Not IsEmpty(.Cells(row, col)) Then
    If Application.CountIf(.Range(.Cells(row, col), _
    .Cells(19, col)), .Cells(row, col).Value) > 1 Then .Cells(row, col).Value = ""
    End If
    End If
    Next row
    End If
    Next col
    End With
    Application.ScreenUpdating = True
    End Sub
    


    Gruß Gerd

    Anzeige
    AW: Doppelte Einträge - Zeile löschen
    05.06.2008 20:54:09
    Konni
    Hallo Gerd,
    Danke, dass Du wieder da bist.
    In Deinem Code ist ein "End If-Abschluss" zuviel.
    
    Sub Doppeleinträge_aus_Spalten_löschen3A()
    Dim row As Long, col As Long
    Application.ScreenUpdating = False
    With ThisWorkbook.Worksheets("Tabelle1") 'ANPASSEN !
    For col = 42 To 49
    If Application.WorksheetFunction.CountA(.Range(.Cells(19, col), .Cells(1018, col))) > 0  _
    Then
    For row = 1018 To 20 Step -1
    If Not IsEmpty(.Cells(row, col)) Then
    If Application.CountIf(.Range(.Cells(row, col), _
    .Cells(19, col)), .Cells(row, col).Value) > 1 Then .Cells(row, col).Value = ""
    End If
     End If
    Next row
    End If
    Next col
    End With
    Application.ScreenUpdating = True
    End Sub
    


    Wenn ich nun den Code laufen lasse, so kommt bei leeren Spalten 42-48, Spalte 49 hat Einträge, wieder die Meldung "Typen unverträglich".
    Schreibe ich jedoch "For col = 49 To 49", so klappt alles einwandfrei. Woran könnte das liegen?
    Viele Grüße: Konni

    Anzeige
    AW: Doppelte Einträge - Zeile löschen
    05.06.2008 22:30:00
    Gerd
    Hallo Konni.
    ein EndIf oberhalb von "next row" war zuviel, ja, sorry.
    Ansonsten verstehe ich deine Fehlermeldung erst mal leider nicht.

    AW: Doppelte Einträge - Zeile löschen
    05.06.2008 22:51:25
    Konni
    Hallo Gerd,
    wenn ich den Code nur auf Spalte 49 festlege "For col = 49 To 49", dann kommt keine Fehlermeldung. Sobald ich aber z.B. die Spalte 48 (ist leer) hinzunehme "For col = 48 To 49" kommt die Fehlermeldung "Typen unverträglich". Ich weiß nicht woran das liegt.
    Gruß: Konni

    AW: Doppelte Einträge - Zeile löschen
    05.06.2008 23:21:59
    Gerd
    Hallo Konni.
    ohne Beispieldatei versagt hier meine Glaskugel ihren Dienst:-)
    Gruß Gerd

    AW: Doppelte Einträge - Zeile löschen
    06.06.2008 10:19:38
    Konni
    Hallo Gerd,
    ich kann die Datei aufgrund ihrer Größe und sensibler Daten nicht hochladen.
    Ich glaube aber den Fehler gefunden zu haben:
    
    Sub Doppeleinträge_aus_Spalten_löschen_und_Texte_auslesen3A()
    Dim row As Long, col As Long 'von Gerd L am 05.06.08
    Application.ScreenUpdating = False
    With ThisWorkbook.Worksheets("Tabelle1") 'ANPASSEN !
    For col = 42 To 49
    If Application.WorksheetFunction.CountA(.Range(.Cells(19, col), .Cells(1018, col))) > 0  _
    _
    Then
    For row = 1018 To 20 Step -1
    If Not IsEmpty(.Cells(row, col)) Then
    If Application.CountIf(.Range(.Cells(row, col), _
    .Cells(19, col)), .Cells(row, col).Value) > 1 Then .Cells(row, col).Value = ""
    End If
    Next row
    End If
    Next col
    End With
    Dim Arr, Text, i, Maxzl As Long, sp As Long 'von Mac4 (Marc) am 03.06.08
    For sp = Columns("AP").Column To Columns("AW").Column
    Maxzl = Cells(Rows.Count, sp).End(xlUp).row
    Arr = Range(Cells(1, sp), Cells(Maxzl, sp))
    For i = 1 To UBound(Arr)
    Text = Text & Arr(i, 1)
    Next i
    Cells(sp - 6, "BB") = Text
    Text = ""
    Next sp
    Application.ScreenUpdating = True
    End Sub
    


    Im Code (freundlicherweise von Marc zur Verfügung gestellt) wird der Text aus den bereinigten Spalten ausgelesen. - Wenn hier irgendeine Spalte leer ist, kommt die Fehlermeldung "Typen unverträglich".
    Kannst Du mir freundlicherweise den Code so modifizieren (wie bei Deinem), dass leere Spalten ignoriert werden?
    Noch etwas: Was bedeutet die - 6 in "Cells(sp - 6, "BB") = Text" und worauf bezieht sich dies?
    Ich weiß zwar, dass damit der Beginn der Textzeile festgelegt wird, kann aber die 6 nicht zuordnen.
    Vielen Dank für Deine Unterstützung und Gruß: Konni

    Anzeige
    AW: Doppelte Einträge - Zeile löschen
    07.06.2008 10:15:37
    Gerd
    Hallo Konni,
    'Cells(Zeilennummer, Spaltennummer)
    'sp= 43 'spaltennummer aus Schleife
    'Cells(sp-6,"BB") ------- cells(37,"BB")
    Wofür "BB" steht, siehst wenn Du in den Excel-Optionen
    Menü Extras-Optionen -Allgemein die Bezugsart auf "Z1S1" umstellst.
    
    Sub a()
    Dim Arr As Variant, Text As String, i As Long, Maxzl As Long, sp As Long
    Dim offs As Long
    offs = 6
    For sp = Columns("AP").Column To Columns("AW").Column
    Maxzl = Cells(Rows.Count, sp).End(xlUp).Row
    Arr = Range(Cells(1, sp), Cells(Maxzl, sp))
    If IsArray(Arr) Then
    For i = 1 To UBound(Arr)
    Text = Text & Arr(i, 1)
    Next i
    Else
    Text = Cells(Maxzl, sp)
    End If
    If Text = "" Then
    offs = offs + 1
    Else
    Cells(sp - offs, "BB") = Text
    End If
    Text = ""
    Next sp
    End Sub
    


    Allerdings geht der zurechtgepfrimelte Code ("kein Wert" - kein Array) jeweils über die gesamte
    Spalte, nicht nur über den Bereich(Zeile 19 - 1008) u. läuft stets "über das" aktiven Blatt.
    Da kannst noch etwas anpassen. Und es gibt natürlich Alternativen.
    Gruß Gerd

    Anzeige
    AW: Doppelte Einträge - Zeile löschen
    08.06.2008 12:19:36
    Konni
    Hallo Gerd,
    ich traue mich fast schon garnicht mehr Dich zu fragen.
    Bei Deinem Code kommt die Fehlermeldung "Mehrfachdeklaration im aktuellen Gültigkeitsbereich". Dabei wird ", i As Long" im Code markiert.
    Du hast Alternativen angedeutet, die nicht die ganze Spaltenlänge durchsuchen! Hast Du so eine Alternative zur Hand? Wie Du weißt sind meine VBA-Kenntnisse auf den Recorder beschränkt.
    Vielen Dank für Deine Unterstützung!!
    Gruß und einen schönen Sonntag: Konni

    AW: Doppelte Einträge - Zeile löschen
    08.06.2008 13:23:00
    Gerd
    Hallo Konni,
    ich habe den Code auf die Zeilen 19 - 1008 eigeschränkt u. die Variable i umbenannt.
    Weitergehende Alterativen würdest Du wahrscheinlich nicht verstehen.
    Bei der mitgeteilten Fehlermeldung hattest die Variable "i" entweder andernorts bereits deklariert
    oder im Code in den DIM-Anwesungen doppelt drin.
    Sub b()
    Dim Arr As Variant, Text As String, Ind As Long, Maxzl As Long, sp As Long
    Dim offs As Long
    offs = 6
    For sp = Columns("AP").Column To Columns("AW").Column
    Maxzl = Application.Min(1008, Cells(Rows.Count, sp).End(xlUp).Row)
    If Maxzl < 19 Then Exit For
    Arr = Range(Cells(19, sp), Cells(Maxzl, sp))
    If IsArray(Arr) Then
    For Ind = 1 To UBound(Arr)
    Text = Text & Arr(Ind, 1)
    Next Ind
    Else
    Text = Cells(Maxzl, sp)
    End If
    If Text = "" Then
    offs = offs + 1
    Else
    Cells(sp - offs, "BB") = Text
    End If
    Text = ""
    Next sp
    P.S.: Jetzt ungetestet.
    Gruß Gerd

    Anzeige
    Tausend Dank, es klappt wunderbar!
    08.06.2008 17:45:00
    Konni
    Mein lieber Gerd,
    Dein neuer Code läuft einwandfrei. Genau so habe ich es mir vorgestellt und gewünscht.
    Du hast mir den Rest des Sonntags gerettet.
    Vielen Dank für Deine masssive Unterstützung!!
    Viele Grüße aus Bietigheim (zw. Karlsruhe und Rastatt): Konni :-))

    Beliebteste Forumthreads (12 Monate)

    Anzeige

    Beliebteste Forumthreads (12 Monate)

    Anzeige
    Anzeige
    Anzeige