VBA - For Each-Schleife

Hallo,

da die letzte Frage ein wenig aus dem Ruder gelaufen ist, möchte ich hier erneut die Frage eröffnen.

Wenn man eine For…Next-Schleife programmiert, hat man einen Zähler, mit dem man arbeiten kann.
So weit, so gut.
Nutzt man eine For…Each-Schleife, benötigt man keinen Zähler, der da irgendwie mit läuft.
Dennoch wird VBA doch irgendwo einen internen Zähler haben, damit er das aktuelle „Item“/Wert oder wie auch immer für sich definieren kann.
Wie kann man auf diesen Zähler zugreifen?

Wenn ich zum Beispiel (!) sage:

Private Sub Constant_demo_Click()
   'fruits is an array
   fruits = Array("apple", "orange", "cherries")
   Dim fruitnames As Variant
 
   'iterating using For each loop.
   For Each I In fruits
        x = Len(I)
        fruitnames = fruitnames & I & Chr(10)
   Next
   
   MsgBox fruitnames
End Sub

kann ich mit x = Len(I) auf die Länge des Textes eingehen.
Wie kann ich aber - ohne das ich auf das Array zugreife (da ich nicht in jeder For-Each-Schleife auf eine Array zugreife) - auf die „Position“ eingehen, bei der sich die For-Each-Schleife gerade befindet?

So etwas wie

x = I.Item

finde ich nicht.
For-Each-Schleifen kann man ja für alle möglichen Auflistungen benutzen: Wörter in einem Dokument, installierte Schriftarten, ein Range-Objekt etc.
und ich möchte auf den internen Zähler zugreifen, auf den vermutlich eben auch die For-Each-Schleife zugreift, damit sie weiß, „bei welchem Item bin ich denn gerade“.

Für antwortweisende Fragen bin ich gern zu haben.
Bitte keine Diskussion, ob Programmierung in VBA sinnvoll, gut, gefährlich oder sonst was ist.
Ich möchte einfach NUR eine Lösung zu meinem Gedankengang.

Danke
Tobi@s

? Das ist aber eigentlich der Sinn einer „for each“-Schleife.

Geht m.W. nicht. Ist auch nicht wirklich sinnvoll, weil du in so einer Schleife nicht von einer bestimmten Reihenfolge der Abarbeitung ausgehen kannst.
Wenn du aus irgendeinem Grund wissen musst, wie viele Elemente schon verarbeitet wurden, kannst du natürlich einen Zähler in der Schleife mitführen.
Alternativ holst du dir mit LBounds(fruits) und UBounds(fruits) die min/max Indizes deines Arrays (LBounds() liefert standardmäßig 0) und baust dir damit eine for…next Schleife.

Gruß,

Kannitverstan

1 Like

Wenn Du objektorientiert programmieren willst, musst Du dich von dem ganzen Zeigergedöns gedanklich verabschieden. Das passt nicht dazu. Du erhälst die Information, die dir das Objekt gibt.

Frage ist also: Was willst Du mit dem Index/dem Zeiger machen?

1 Like

Wie kann ich … auf die „Position“ eingehen, bei der sich die For-Each-Schleife gerade befindet?
So etwas wie x = I.Item

Hallo Tobi@s

Ohne einen Zähler sehe ich wie Kannitverstan keine Lösung. Deshalb hilft Dir das folgende wahrscheinlich auch nicht. Aber es ist wenigstens nicht sinnvoll, gut, gefährlich oder sonst was. :relaxed:
Grüsse Niclaus

Option Base 1
Sub m4aa()
fruits = Array("apple", "orange", "cherries", "pears")
For i = 1 To UBound(fruits)
    MsgBox i & ". " & fruits(i) & " (mit " & Len(fruits(i)) & " Buchstaben)"
    fruitnames = fruitnames & i & ". " & fruits(i) & Chr(10)
Next i
    MsgBox fruitnames
End Sub

„Option Base 1“: Damit beginnt der Zähler des Arrays mit 1. Ohne diese Option beginnt er mit 0.

Toll. Und als nächstes installier ich mir ein Plugin für „Goto“.

Genau. Und deshalb nutzt man halt keine For…Each, wenn man einen Zähler will. Oder bastelt sich einen selber. Ganz einfach eigentlich.

1 Like

Hallo!

Nein, das ist nicht notwendig, und auch gar nicht gewollt.

Vielleicht ein kleiner Exkurs:

Ich kann kein VBA, aber Python. Dort ist FOR-EACH so tief verwurzelt, daß es gar kein FOR-NEXT gibt, sondern ausschließlich FOR-EACH. Und das geht so weit, daß man über die Zeilen einer Datei loopen kann:

datei=open("MyFile.txt")
for zeile in datei:
    print(zeile)

(Ja, das ist echter, lauffähger Code)
Jetzt stell dir vor, daß die Datei 1 Terabyte groß ist. Es ist unmöglich, die erstmal komplett ins RAM zu laden. Der Code oben hat damit aber kein Problem, weil er in jedem Schleifenduchlauf immer nur eine Zeile liest und im RAM hat.
Allerdings weiß das Programm gar nicht, wie viele Zeilen die Datei überhaupt hat (die Zeilen können ja unterschiedlich lang sein). Es merkt nur irgendwann, daß es das Dateiende erreicht hat.

Technisch weiß das Programm, welches Byte als nächstes aus der Datei gelesen werden soll. Und wenn es so weit ist, werden so lange Bytes gelesen, bis ein Zeilenende erreicht ist, und die Bytes werden zurückgegeben. Es werden also nicht mal die Zeilen gezählt, das einzige, was es vielleicht gibt, ist die Lesepositon. Es gibt dabei keinen Zusammenhang zwischen der Leseposition und der Anzahl gelesener Zeilen, eben wegen der unterschiedlichen Zeilenlänge.
Nun kann man eine FOR-EACH-Schleife auch auf ein Array anwenden, da gibt es sicher auch eine Leseposition, und die wird auch mit der Elementnummer übereinstimmen. Aber da kommst du üblicherweise nicht dran.

Im Prinzip zeigt das recht gut den Zweck einer FOR-EACH-Schleife. Es geht darum, jedes Element einzeln zu behandeln, und dabei ggf. gar nicht so genau zu wissen, wie viele Elemente es überhaupt gibt.

2 Like

ich programmiere aber (noch) nicht objektorientiert. Für das was ich mache, reicht „normales“ Programmieren aus.

An dieser Stelle ging es erst mal nur darum, zu erfahren, ob ich vielleicht etwas einfach noch nicht kenne.
Zum Anderen hatte ich das „Problem“, dass ich alle Worte eines Dokuments durch gehen will und nur wenn eine Bestimmte Bedingung auf das Wort zutrifft, möchte ich wissen, „wie heißt das Wort davor?“. Und bei ListBox etc. gibt es ja interne Index, mit der man (ohne Zähler) feststellen kann „ich bin jetzt beim x. Element“. Und das dachte ich, gibt es evtl auch bei For-Each.

hi,

Ich stelle fest:
Die Antwort steht bereits in der Erklärung zu deinem Beispiel.

temp=I braucht keinen counter.
Du willst ja letztlich gar nicht wissen, an welcher Stelle du bist. Du willst nur den vorherigen Wert.

grüße
lipi

Du nutzt ein OOP-Feature. Folglich musst Du in OOP denken, wenn Du dieses Feature nutzt, um die Funktionsweise zu verstehen.

1 Like