2.2k Aufrufe
Gefragt in Tabellenkalkulation von desiato Mitglied (115 Punkte)
Hallo,

ich habe eine Eingabemaske erstellt, deren Werte in einem Tabellenblatt spaltenweise eingetragen werden. Das können beliebig viele Datensätze sein, Spalte C, Zeile 4 bis x ist der erste Datensatz, Spalte D, Zeile 4 bis x der Zweite usw.

Ich würde gerne VOR dem Schreiben des aktuellen Datensatzes in das Tabellenblatt überprüfen, ob es diesen schon einmal gibt. Einen Zähler, wie viele Spalten beschrieben wurden, habe ich schon, das soll i sein.
Jetzt wollte ich das folgendermaßen machen (hatte ich erwähnt, das ich VBA-Anfänger bin?):

Range("c4").select
For n = 0 To i - 1
If ActiveCell.Offset(2, n) = cbo_Art1.Value Then
If ActiveCell.Offset(3, n) = cbo_entnahme1.Value Then
If ActiveCell.Offset(5, n) = cbo_Art2.Value Then
If ActiveCell.Offset(6, n) = cbo_Entnahme2.Value Then
If ActiveCell.Offset(9, n) = cbo_Abarbeitung Then
MsgBox "Variante vorhanden"
ExitFor
End If
End If
End If
End If
End If
End If

Beim Ausführen sagt er mir "For ohne Next", aber egal wo ich das Next hinschreibe, kommt die Meldung "Next ohne For".

Vielleicht kann mir jemand weiter helfen oder weiß eine andere Lösung.

Danke und guten Rutsch :-)

5 Antworten

0 Punkte
Beantwortet von
Hi,

In Deinem obigen CodeSchnippsel dürfte ein "End If" zuviel drin sein, ExitFor sollte auseinander geschrieben werden, und wenn das überschüssige "End If" weg ist, dann würde das geforderte "next" am Ende dieses Schnippsels landen. Wenn Du jede IF-Abfrage (mittels TAB) einrücken würdest, wäre es Dir sicher selbst aufgefallen.

Das sähe dann ungefähr aus wie folgt:
Range("c4").Select
For n = 0 To i - 1
If ActiveCell.Offset(2, n) = cbo_Art1.Value Then
If ActiveCell.Offset(3, n) = cbo_entnahme1.Value Then
If ActiveCell.Offset(5, n) = cbo_Art2.Value Then
If ActiveCell.Offset(6, n) = cbo_Entnahme2.Value Then
If ActiveCell.Offset(9, n) = cbo_Abarbeitung Then
MsgBox "Variante vorhanden"
Exit For
End If
End If
End If
End If
End If
Next n


Da Du nun selbst schreibst, dass Du noch lernender "VBA-Anfänger" bist, lass mich doch gleich noch auf Deine erste Codezeile eingehen: Auf .select (und auch auf .activate) kann man weitestgehend verzichten. Hier einmal eine nette kleine "Aufklärung" dazu.
Nun könnte man in Deinem Codeschnippsel jedes "ActiveCell.Offset(x,x)" durch ein "Range("c4").Offset(x,x)" ersetzen. Dies wiederum erschwert es mMn den Code anzupassen/zu pflegen. Daher würde ich dann eher zu einer "With"-Anweisung greifen wollen.

Das Ergebnis sähe dann ungefähr aus wie folgt:
With Range("c4")
For n = 0 To i - 1
If .Offset(2, n) = cbo_Art1.Value Then
If .Offset(3, n) = cbo_entnahme1.Value Then
If .Offset(5, n) = cbo_Art2.Value Then
If .Offset(6, n) = cbo_Entnahme2.Value Then
If .Offset(9, n) = cbo_Abarbeitung Then
MsgBox "Variante vorhanden"
Exit For
End If
End If
End If
End If
End If
Next n
End With


bye
malSchauen
0 Punkte
Beantwortet von desiato Mitglied (115 Punkte)
Hallo mal schauen,

danke zuerst einmal für die schnelle Hilfe. Ich hab so oft in dem Makro rumgewuselt, dass ich das eine End If wohl übersehen habe.

Ich habe es inzwischen etwas anders gelöst, indem ich eine einzige IF-Bedingung mit vielen ANDs gemacht habe.

Wäre die Verschachtelung denn besser/übersichtlicher bzw. programmiertechnisch eleganter?

Danke aber auch für den Tip mit dem with, das spart unter Umständen viel Schreibarbeit.
0 Punkte
Beantwortet von
Hi,

Ich habe es inzwischen etwas anders gelöst, indem ich eine einzige IF-Bedingung mit vielen ANDs gemacht habe.


War auch mein erster Gedanke. Wobei mir da noch andere Ansätze "durch den Kopf gegangen" sind. Durch Deinen selbstgewählten "VBA-Anfängerstatus" habe ich mich dann aber zu obiger Antwort entschieden.

Wäre die Verschachtelung denn besser/übersichtlicher bzw. programmiertechnisch eleganter?


Die Frage ist mMn nicht so einfach zu beantworten. Zum einen dürften da pers. Vorlieben eine grosse Rolle spielen, dann auch, ob Du den Code nur allein verstehen musst, oder ob auch andere daran mitarbeiten wollen/sollen. Und auch die Grösse des Projektes ist wohl nicht zu vernachlässigen. Bei grossen Datenmengen und wirklich häufiger Benutzung des entsprechenden Codeabschnitts würd ich wohl sogar die Laufzeit über der "Übersichtlichkeit" ansiedeln wollen. Soll heisen: Ich würde dann testen wollen, welche Variante (If-Schachtelung<->AND-Verknüpfung (um bei obigem Beispiel zu bleiben)) weniger Laufzeit beansprucht. Und die schnellere Variante würde ich dann ggf. bevorzugen. So zumindest sähe meine Herangehensweise aus, ohne damit Deine Frage wirklich beantwortet zu haben.

bye
malSchauen
0 Punkte
Beantwortet von desiato Mitglied (115 Punkte)
Hallo mal schauen,

die Vorgehensweise mit IF...AND war für mich die schnellste Lösung. Ich bin blutiger VBA-Anfänger, habe vor gefühlten 100 Jahren mal ein wenig TurboPascal gelernt, deshalb ist mir die Logik nicht so ganz unbekannt.

Kann man denn die Laufzeit irgendwie bestimmen oder ist das eher gefühlt? Ich könnte mir vorstellen - rein logisch - das die IF...AND etwas langsamer sein könnte, da der ganze Datensatz geprüft werden muss. Bei der Verschachtelung ist ja ein früherer Ausstieg möglich.

Was die Lesbarkeit des Codes angeht, war eben die Frage, ob es programmiertechnische Konventionen gibt, dass man die eine oder andere Lösung vorzieht. Ob andere den Code verstehen, kann man ja persönlich immer schlecht beurteilen.
0 Punkte
Beantwortet von
Hi,

Kann man denn die Laufzeit irgendwie bestimmen oder ist das eher gefühlt?

Wenn Du den Unterschied schon "fühlen" kannst, dann wirst Du je nach Project wohl schon selbst tätig werden, bzw. die Wahl wird einfach sein. Aber man kann sie auch messen. Ein Beispiel, wie es gehen könnte, habe ich hier in Antwort 19 einmal versucht einzusetzen.

Ich könnte mir vorstellen - rein logisch - das die IF...AND etwas langsamer sein könnte, da der ...

Vorstellen könnt ich mir auch so einiges. ;-) Diesen speziellen Fall habe ich, der ich selbst VBA nur so aus Hobby verwende und selbst immernoch Lernender bin, noch nie wirklich getestet. Das müsstest Du bei Bedarf schonmal selbst machen.

... , ob es programmiertechnische Konventionen gibt, dass man die eine oder andere Lösung vorzieht. ...

Möglich, dass es da welche gibt. Da ich aber selbst eher im HobbyBereich "arbeite", sind sie mir nicht wirklich bekannt. Ich schau mir aber gern mal Code in dem ein oder anderen Forum an, und ziehe dann das was mir gefällt (auch in Richtung Aufbau/Gliederung) heraus, um selbst davon zu lernen und meinen eigenen Code weiter zu "verbessern". Und früher oder später findet man dabei dann auch Code, der deutlich schneller ist, als der eigene. Bis Du solchen Code findest, oder eigene Tests anstellst, hilft Dir evtl. dieses Tutorial etwas weiter. (In Teil3 findet sich dann auch noch eine weitere Art der "ZeitMessung".)

bye
malSchauen
... der weiss, dass es immernoch keine wirklich konkrete Antwort war... ;-)
...