Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
1716to1720
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

Wie diesen Code optimieren/beschleunigen?

Wie diesen Code optimieren/beschleunigen?
18.10.2019 16:08:25
AleXSR700
Hi wertes Forum,
ich habe nun ein neues kleines Problem.
Ich nutze folgenden Code, um alle leere Spalten in einer bestimmten Tabelle zu löschen. Dabei darf nur der Inhalt der Tabelle und nicht die ganze Spalte gelöscht werden.
With Worksheets("Infos")
InfoRow = 22
InfoColumn = 1
Dim CleanColumn As Long
For CleanColumn = .Cells(23, Columns.Count).End(xlToLeft).Column To 4 Step -1
If .Cells(Rows.Count, CleanColumn).End(xlUp).Row = 23 Then _
Call .Range(.Cells(22, CleanColumn), .Cells(Rows.Count, CleanColumn)).Delete(Shift:=xlShiftToLeft)
Next
End With
Das Problem ist, dass die Tabellen mittlerweile etwa 150 Spalten breit und 30 Zeilen lang sind. Dies liegt daran, dass die Datenbank derart viele Variablen hat. Die meisten Aufträge nutzen davon nur etwa. 10, aber trotzdem müssen alle zur Auswahl vorhanden sein damit alle Zuordnungskombinationen funktionieren. Deshalb dauert dieser Code mittlerweile etwa 15 min bis er fertig ist. Und das ist leider etwas zu lange. Vor allem in den Fällen, in denen von den 150 Spalten nur 10 verwendet wurden.
Gibt es einen Weg den Code zu optimieren?
Ziel:
Prüfen, ob in irgendeiner Zeile unter irgendeiner Spalte der Kopfzeile ein Wert steht.
Falls es hilft: es kann nur in den Zeilen ein Wert stehen, die in der ersten Spalte einen Wert stehen haben. Denn der erste Wert einer jeden Zeile MUSS existieren. Wenn hier keiner existiert, dann sind alle Spalten dieser Zeile leer.
Vielen lieben Dank für eure Hilfe und viele Grüße
Alex

21
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: Wie diesen Code optimieren/beschleunigen?
18.10.2019 16:27:52
AleXSR700
Anbei eine Beispieldatei.
Die Kreuze werden durch den VBA Code zugeordnet. Wenn der Code fertig ist, soll aufgeräumt werden.
In dieser Beispieltabelle bedeutet dies, dass die Zellen B1 bis B7, F1 bis F7, G1 bis G7 und I1 bis K7 gelöscht und die danebenliegenden nach links verschoben werden müssten.
https://www.herber.de/bbs/user/132586.xlsx
AW: Wie diesen Code optimieren/beschleunigen?
18.10.2019 16:28:11
Daniel
Hi
With Sheets("Info").UsedRange
With .Rows(.Rows.Count + 1)
.FormulaR1C1 = "=IF(AND(Column(RC)>3,CountA(R24C:R[-1]C)=0),1,"""")"
If WorksheetFunction.Sum(.Cells) > 0 Then
Intersect(.SpecialCells(xlCellTypeFormulas, 1).EntireColumn, _
.Worksheet.Range("22:" & .Row)).Delete Shift:=xlToLeft
End If
.ClearContents
End With
End With
Gruß Daniel
Anzeige
dieser Code basiert jetzt auf deinem
18.10.2019 16:31:10
Daniel
Beispielcode und nicht auf der nachgeschobenen Beispieldatei!
bitte beim testen beachten.
Gruß Daniel
noch schneller
18.10.2019 16:45:26
Daniel
hi
noch ne kleine Optimierung, mit der das ganze noch schneller geht:
With Sheets("Info").UsedRange
With .Rows(.Rows.Count + 1)
.FormulaR1C1 = "=IF(AND(Column(RC)>3,CountA(R24C:R[-1]C)=0),1,"""")"
If WorksheetFunction.Sum(.Cells) > 0 Then
.Worksheet.Range("22:" & .Row).Sort key1:=.Cells(1, 1), _
order1:=xlDescending, Header:=xlNo, Orientation:=2
Intersect(.SpecialCells(xlCellTypeFormulas, 1).EntireColumn, _
.Worksheet.Range("22:" & .Row)).Delete Shift:=xlToLeft
End If
.ClearContents
End With
End With
Achtung: der Code benutzt die Sortierung und sortiert dabei die Spalten und nicht die Zeilen, wie es normalerweise üblich ist.
Da sich Excel die Sortiereinstellungen merkt, solltest du diese vor oder beim nächsten Sortieren umstellen, da wir diese Einstellung normalerweise übersehen bzw davon ausgehen, dass ohne explizite Angabe nach Zeilen sortiert wird.
Gruß Daniel
Anzeige
AW: noch schneller
18.10.2019 17:30:07
AleXSR700
Hallo Daniel,
vielen Dank für deine Antwort.
Ich habe mal versucht mit deinem Code zu experimentieren aber bekomme einen Anwendungs- oder Typfehler bei
.Worksheet.Range("9:" & .Row).Sort key1:=.Cells(1, 1), _
order1:=xlDescending, Header:=xlNo, Orientation:=2
Ist es nötig die Sortierungsart zu ändern?
Vielen Dank für deine Hilfe
Alex
AW: noch schneller
18.10.2019 17:37:41
Daniel
HI
du kannst das sortieren auch weglassen.
ist halt nur so dass das Löschen von Zellen wesentlich schneller geht, wenn die zu löschenden Zellen nicht wild auf dem Blatt verteilt sind, sondern möglichst einen lückenlosen Zellblock bilden.
und hierfür muss man eben die Spalten umsortieren, machbar ist dies, weil ich sie ja über die Formel gekennzeichnet habe.
den Fehler kann ich nicht nachvollziehen, ich habe den Code getestet und da lief er ohne Fehler durch.
der Sortierbefehl entspricht dem Sortierbefehl von Excel 2003 und früher und müsste daher auf jeden Fall funktioneren.
du kannst ja ggf die Datei mal hochladen.
Gruß Daniel
Anzeige
AW: noch schneller
18.10.2019 17:55:04
AleXSR700
Hallo Daniel,
ich glaube, dass ich einfach die Syntax der RC Schreibweise gerade verpeile.
Ich bin auch bei deinen Angaben nicht 100 % sicher, weshalb die so sind wie sie sind. Sie sind bestimmt richtig, nur verstehe ich es nicht und kriege es deshalb nicht angepasst.
Hier mal die Beispieldatei mit dem (von mir falsch) angepassten Code.
https://www.herber.de/bbs/user/132589.xlsm
Eigentlich sollte er erst ab Spalte 4 anfangen zu suchen. Und aus irgendeinem Grund nimmt er die falsche Range, denn er beginnt eine Zeile über der Formel und nicht ganz oben unter der Kopfzeile. Er müsste ja anhand der Anzahl Werte in der ersten Spalte zählen. Und dann um diese Anzahl über der Formel beginnen.
In solchen Momenten kommt man sich vor wie der erste Mensch :-(
Viele Grüße
Alex
Anzeige
AW: noch schneller
18.10.2019 18:04:22
Daniel
Hi
die Syntax ist doch ganz einfach:
in der R1C1-Addressierungsart steht der R der Zelladresse für Row (Zeile) und danach folgt die Zeilennummer.
das R24 steht für Zeile 24 ganz simpel
in deinem Beispielcode war Zeile 24 der Beginn des Zellbereichs, der geprüft werden musste ob die Spalte leer ist oder nicht.
Wenn das jetzt eine andere Zeile ist, dann musst du die Formel eben anpassen und statt der 24 die Zeilennummer der obersten zu prüfenden Zeile eintragen.
wenn du den Code im Einzelstep durchgehst dann solltest du dir nach dem einfügen der Formel diese mal in der Tabelle anschauen, dann siehst du ja, was abgeht.
und denn du die Formel korrigieren musst, dann kannst du das in der Tabelle testen, dann die Änderung in den Code übernehmen, die Programmezeile nochmal ausführen und dann dann den Code weiter laufen lassen.
Gruß Daniel
Anzeige
AW: noch schneller
19.10.2019 12:28:37
AleXSR700
Hallo Daniel,
ja, die Zuordnung hatte ich dann schon korrekt verstanden. Aber was nicht klappt, ist dass er dann auch die zugehörige Kopfzeile mit verschiebt.
Nehmen wir mal die Beispieldatei. Hier habe ich es geändert auf
Sub Auftragsübersicht_anlegen()
Application.ScreenUpdating = False
With Worksheets("Auftragsübersicht").UsedRange
With .Rows(.Rows.Count + 1)
.FormulaR1C1 = "=IF(AND(Column(RC)>3,CountA(R3C:R[-1]C)=0),1,"""")"
If WorksheetFunction.Sum(.Cells) > 0 Then
.Worksheet.Range("3:" & .Row).Sort key1:=.Cells(1, 1), _
order1:=xlDescending, Header:=xlNo, Orientation:=2
Intersect(.SpecialCells(xlCellTypeFormulas, 1).EntireColumn, _
.Worksheet.Range("3:" & .Row)).Delete Shift:=xlToLeft
End If
.ClearContents
End With
End With
End Sub
Das funktioniert prinzipiell, aber er sortiert nur den Inhalt der Tabelle nach vorne. Die Zuordnung zur Kopfzeile geht dabei aber verloren. Er muss ja ab Zeile 1 verschieben. Ich dachte, dass ich dazu dann diese Anpassung machen müsste:
              .Worksheet.Range("1:" & .Row).Sort key1:=.Cells(1, 1), _
order1:=xlDescending, Header:=xlNo, Orientation:=2
Intersect(.SpecialCells(xlCellTypeFormulas, 1).EntireColumn, _
.Worksheet.Range("1:" & .Row)).Delete Shift:=xlToLeft
Das funktioniert aber nicht. Deshalb suche ich meinen Denkfehler und verstehe nicht so ganz, wieso das nicht klappt.
Anzeige
AW: noch schneller
19.10.2019 16:18:55
Daniel
Also bei mir in meiner Datei hats funktioniert.
Mache es so wie ich dann gehts auch bei dir.
Gruß Daniel
AW: noch schneller
21.10.2019 12:21:17
AleXSR700
Hallo Daniel,
ich versuche es natürlich zu verstehen, damit ich es auch auf weitere Tabellen anwenden kann, die etwas anders formatiert sind.
Ich glaube den Fehler aber gefunden zu haben. Das Problem war, dass die allererste Zelle verbunden war. Sprich die Zelle A1 war mit der A2 verbunden und das hat ihn dann wohl zum Fehler gebracht.
Der Code funktioniert jetzt super!
Gäbe es eine Möglichkeit ihn jetzt noch nach einem bestimmten Namen sortieren zu lassen?
Sprich, wenn in der Spalte, in der in der Kopfzeile "Primär" steht ein Wert vorhanden ist, dann soll er diese Spalte zur neuen vierten Spalte machen und danach erst alle anderen aufschieben?
Anzeige
AW: noch schneller
21.10.2019 14:20:08
Daniel
HI
so dinge kannst du jetzt einfach über die Formel regeln.
schreibe die Formel so um, dass sie als Ergebnis folgendes ausgibt:
a) für alle Spalten, die gelöscht werden sollen einen Text (was ist egal, fürs testen ist "xxx" immer gut)
b) für alle Spalten die stehen bleiben müssen, die Reihenfolgenummer als Zahl, dh für die ersten 3 Spalten die 1, für die "Primär-Spalte" die 2 und für alle anderen Spalten die Stehen bleiben sollen die 3
(mach das zuerst von Hand direkt in der Tabelle, bei Excel-gut solltest du das hinbekommen, dann kannst du dir im Direktfenster mit ?Selection.FormulaR1C1 die Formel für den VBA-Code anzeigen lassen und von dort in den Code kopieren, lediglich die Dopplung der Anführungszeichen die zur Formel gehören musst du noch machen)
beim Sortieren bekommst du dann die richtige Reihenfolge.
da jetzt im Gegensatz zum alten Code die Spalten mit Zahl stehenbleiben sollen und die Spalten mit Text gelöscht werden, musst du hier noch
.SpecialCells(xlCellTypeFormulas, 1)

aus der 1 eine 2 machen (die 1 steht für Zahlen, die 2 für Texte)
Gruß Daniel
Anzeige
AW: noch schneller
21.10.2019 15:46:05
AleXSR700
Pfuh, ich finde es deutlich erschwert Formelfehler in VBA zu finden.
Ich habe eine verschachtelte WENN Funktion und finde den Fehler nicht.
Gedacht wäre, dass wenn in der Kopfzeile der Wert 452 steht, er den Zellwert auf 1 setzt. Wenn die Range leer ist, dann "Delete" und wenn nicht leer und nicht 452 dann den Wert 2. Darüber hinaus bleiben die ersten drei leer, also "".
.FormulaR1C1 = "=IF(Column(RC)>3,(IF(AND(R8C=452,CountA(R10C:R[-1]C)0)),1,(IF(CountA(R10C:R[-1]C)=0),""Delete"",2)),"""")"
WENN die Spaltennummer>3 dann [WENN sowohl R8C=452 als auch Range nicht leer dann 1];[ansonsten WENN die Zellen leer dann Delete und wenn nicht leer dann 2].
Habe ich einen Syntaxfehler drin oder finde ich den Klammerfehler nicht?
Anzeige
AW: noch schneller
21.10.2019 16:07:44
Daniel
HI
es ist einfacher, die Formel erstmal von Hand in der Zelle zu entwickeln und erst dann, wenn sie funktioniert, den Text für das Makro ermitteln, das geht dann ja einfach mit dem ?Selection.FormulaR1C1 (dabei kannst du dir auch gleich die Anführungzeichen verdoppeln lassen, dann musst du die Formel nur noch kopieren)
vielleicht ist es für dich logischer die Wenns in dieser Reihenfolge zu schachteln:
ich habe mir angewöhnt, in den WAHR-Teil des Wenns möglichst die kürzere Teilformel zu legen und die längere in den FALSCH-Teil.
=Wenn(Spalte()
Gruß Daniel
AW: noch schneller
22.10.2019 11:28:21
AleXSR700
Hallo Daniel,
es hat nun geklappt. Es stimmt schon: je kürzer man die Formel hält desto leichter findet man den Fehler.
Aber für die Zukunft: wie kann man denn eine Formel in R1C1 Schreibweise konvertieren, ohne VBA einzusetzen? Kann das Excel direkt?
Unter "?Selection.FormulaR1C1" konnte ich auch per Google nichts finden außer VBA Skripten.
AW: noch schneller
22.10.2019 11:35:44
Daniel
HI
du kannst über Datei - Optionen - Formeln - Bezugsart - Z1S1 auf diese Bezugart umstellen, allerdings in Excel halt in der Landestypischen Schreibweise.
dann kannst du auch direkt in Excel mit dieser Bezugsart arbeiten. Du kannst immer problemlos zwischen beiden Schreibweisen umschalten.
fürs normale arbeiten ist A1 praktischer, weil man Zeilen und Spalten nicht verwechseln kann und es anschaulicher ist, aber für die Programmierung finde ich das Z1S1 bzw R1C1 praktischer, weil dann bei der Beschreibung von relativen Zellbezügen nicht mehr beachten muss, welches die Zielzelle ist, in welche die Formel als erstes geschrieben wird.
Gruß Daniel
AW: noch schneller
24.10.2019 12:04:44
AleXSR700
Hallo Daniel,
ja, das wusste ich. Aber das zeigt mir nur die Bezugsart korrekt an und ändert nicht die Formelsyntax. Oder habe ich da etwas übersehen? Ich habe es zwar noch nicht ausprobiert, aber ich nehme mal nicht an, dass ich "Anzahl" statt "CountA" in VBA benutzen kann.
Ich dachte, dass man sich die komplette Formel dann in die R1C1-VBA Syntax umschreiben lassen kann.
AW: noch schneller
24.10.2019 13:53:47
Daniel
HI
du hast in VBA 4 verschiedene Varianten, wie du eine Formel in eine Zelle schrieben kannst.
du kannst jede der 4 Varianten frei verwenden, du musst die Variante auch immer explizit angeben:
.Formula = "=Formel mit A1-Adressen in englisch"
.FormulaLocal = "=Formel mit A1-Adressen in landestypischer Schreibeise (so wie du in Excel arbeitest)"
.FormulaR1C1 = "=Formel mit R1C1-Adressen in englisch"
.FormulaR1C1Local = "=Formel mit R1C1/Z1S1-Adressen in landestypischer Schreibweise"

wenn du schon eine Formel in einer Zelle stehen hast, kannst du dir immer im Direktfenster des VBA-Edtiors die Formel in allen 4 Schreibweisen anzeigen lassen
theoretisch gibt's auch noch .Value = "=Formel mit A1-Adressen in englisch"
Wie gesagt, du kannst die 4 Varianten frei verwenden.
ich bevorzuge in VBA das .FormulaR1C1 weil
- es in allen Ländervarianten funktioniert
- die R1C1-Adressierungsart bei relativen Zellbezügen einfacher ist, man dann die Formel unabhängig von der Zielzelle schreiben kann (bei A1-Adressierungsart muss ich beim Schreiben von Formeln mit relativen Zellbezügen wissen, in welche Zelle die Formel geschrieben wird)
- diese Schreibweise vom Makrorecorder aufgezeichnet wird.
Gruß Daniel
AW: Wie diesen Code optimieren/beschleunigen?
18.10.2019 16:31:17
mmat
Hallo,
1. Die üblichen Verdächtigen:

Application.Calculation = xlManual
Application.ScreenUpdating = False

das wird hier im Forum so oft genannt, dass ich mir eine detailliertere Ausführung schenke.
2. Wahrscheinlich ist das Folgende der Zeitfresser
Call .Range(.Cells(22, CleanColumn), .Cells(Rows.Count, CleanColumn)).Delete(Shift:=xlShiftToLeft)
das löscht alle Zeilen ab Zeile 22 abwärts, aber du hast ja angabegemäß nur 30 Nutzzeilen.
Also:

Call .Range(.Cells(22, CleanColumn), .Cells(52, CleanColumn)).Delete(Shift:=xlShiftToLeft)
vg, MM
AW: Wie diesen Code optimieren/beschleunigen?
18.10.2019 17:32:23
AleXSR700
Hallo MM,
ScreenUpdating ist natürlich abgeschaltet.
Ich habe in dem Beispiel nur 30 Zeilen. Die Anzahl der Zeilen hängt aber von der Quelldatei ab, die eingelesen wird.
Es können also mal 3 Zeilen mit Daten sein und es könnten auch 300 Zeilen mit Daten sein. Sicher ist nur, dass die erste Spalte immer gefüllt ist und es nur so viele Zeilen mit Daten gibt, wie es Zeilen mit Daten in Spalte A gibt.
AW: Wie diesen Code optimieren/beschleunigen?
18.10.2019 17:45:50
Daniel
Hi
für die Geschwindigkeit spielt hier die Anzahl der Zeilen überhaupt keine Rolle.
Entscheiden ist, wieviele einzelnen Zellblöcke gelöscht werden müssen.
deren Größe spielt keine Rolle, es geht allein um die Anzahl der Blöcke.
der Knackpunkt ist, dass Excel beim Löschen von Zellen prüfen muss, ob in irgendeiner geöffneten Datei Formeln, Bedingte Formate, Namen oder Datengültigkeitsprüfungen vorhanden sind, deren Zellbezüge beim Löschen der Zellen ggf angepasst werden müssen. diese Aufgabe kann Excel immer für einen rechteckigen Zellblock durchführen, wie groß dieser Block ist, spielt keine Rolle.
Diese Funktion kann auch nicht abgeschaltet werden, daher bringen die klassischen "Get More Speed"-Optionen beim Löschen von Zellen nur wenig.
Das einzige was hilft, ist das Sortieren um so die Zellen möglichst in einem Block löschen zu können.
Beim Löschen von Zeilen kann man auch das Duplikate-Entfernen einsezten, weil beim Duplikate-Entfernen die Anpassung der Zellbezüge nicht erfolgt und es deswegen sehr schnell ist, aber das gibt's halt nur für Zeilen und nicht für Spalten.
Gruß Daniel

286 Forumthreads zu ähnlichen Themen

Anzeige
Anzeige
Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige