Wie löse ich das "For Each Cell In Range" Problem?

3 Antworten

Vom Fragesteller als hilfreich ausgezeichnet

Bei verbundenen Zellen zählt beim Inhalt immer nur die oberste linke Zelle des verbundnen Bereichs, so wie IchMalWieder es ja erklärt hat. Eine möglickeit herauszufinden, ob du gerade die richtige Zelle abfragst ist die Zelle zu aktivieren und ihre Adresse mit der Adresse des aktuellen Objekts der Schleife zu vergleichen.

Teste mal das an

Sub test()

Dim cell As Range, Auswahl As Range
Set Auswahl = Selection
For Each cell In Auswahl
    cell.Activate
    Debug.Print cell.Address & "=>" & ActiveCell.Address
Next cell

End Sub

und wähle auch mal verbundene Zellen aus. Ich denke im Direktbereich wirst du dann schon sehen, was ich meine.

Haha, was ist ein Direktbereich? Und wie müsste ich das in meinen Code einbauen?

0
@fx8350

Wenn du im VBA Editor Strg + g drückst sollte ein neues Fenster erscheinen. Darin kannst du auch Code direkt eingeben und ausführen, aber es werden auch alles angezeigt, was du mit Debug.print dahin sendest. Probier es mal aus.

1
@LtLTSmash

So, hi. Erst einmal danke. Nur leider verstehe ich nur Bahnhof. Ich habe nun einen markierten Zellbereich G13 bis S20 bzw. dieser Bereich heißt Criterion1. Nun soll geprüft werden ob in einer dieser Zelle Inhalt ist und der Code entsprechend weiterlaufen. Ich verstehe leider nicht einmal, wie ich jetzt Deinen Code ausführen soll mit dem Direktbereich.

0
@fx8350

Mist, habe es über den Direktbereich ausführen können. Das Debug.Print veranschaulicht mir also in diesem Fall, welche Zellen sich in dem markierten Bereich befinden. Nur wie kann ich das nun in meinen Code einbinden?

Es geht quasi um diese beiden Prüfungen:

Public Function checkdeletion() As Boolean
    Dim emptySelection As Boolean: emptySelection = True
    Dim cell As Range, msg As String
    For Each cell In selection
    emptySelection = emptySelection And IsEmpty(cell)
    If emptySelection = False Then
    Exit For
    End If
    MsgBox "Kein Merkmal vorhanden.", vbOKOnly + vbExclamation, ""
    Exit Function
    Next
    msg = MsgBox("Soll das Merkmal gelöscht werden?", vbYesNo + vbQuestion, "")
    If msg = vbYes Then
    Call CriterionVar
    Call InspectionFeatures
    Else
    Exit Function
    End If
End Function


Public Function checkselection() As Boolean
    Dim emptySelection As Boolean: emptySelection = True
    Dim cell As Range, msg As String
    For Each cell In selection
    emptySelection = emptySelection And IsEmpty(cell)
    If emptySelection = False Then
    Exit For
    End If
    Call CriterionVar
    Call InspectionCriterion
    Exit Function
    Next
    checkselection = emptySelection
    msg = MsgBox("Bereich ist nicht leer!" & vbCrLf & "Fortfahren und aktuellen Eintrag überschreiben?", vbYesNo + vbQuestion, "")
    If msg = vbYes Then
    Call CriterionVar
    Call InspectionFeatures
    Call InspectionCriterion
    Else
    Exit Function
    End If
End Function
0
@fx8350

Puhh, jetzt muss ich mich da erst mal wieder reindenken.

Also den Code den ich Ursprünglich gepostet habe kannst nicht komplett im Direktbereich ausführen. Im Direktbereich kann man nur eine einzelne Zeile ausführen.

Also z.B. du gibst da ein

activecell.Interior.Color = RGB(255,0,0)

und drückst dann enter, dann ist die auswählte Zelle rot. Damit kann man Codeteile testen ohne ein Sub definieren zu müssen.

Worum es mir aber eigenlich ging ist die debug funktion. mit dem Befehl debug.print kannst du im laufenden Code dir Werte ins Direktfenster schreiben lassen die du dann zum debuggen nutzen kannst. In meinem Codebeispiel solltest du nur sehen das die Adresse des aktuellen Cell Objektes nicht unbedingt gleich der Adresse sein muss den die Zelle im händisch aktivierten Fall haben muss. Da ging es ja um verbundene Zellen.

1
@fx8350

Zu deinen Funktionen, das debug.print brauchst du nicht, es ging ja nur darum dir zu zeigen wie das mit den verbundenen Zellen in Excel und in VBA aussieht.

Erklaäre evtl nochmal was genau dein Code machen soll. Ich verstehe z.B. nicht wirklich was z.B. das soll

 emptySelection = emptySelection And IsEmpty(cell)
1
@LtLTSmash

Haha, also der Code prüft, ob die selektierte Zelle (in diesem Fall aber ein Zellverbund) Inhalt hat. Wenn dort etwas steht kommt die MsgBox "Kein Merkmal vorhanden..." oder im anderen Code "Bereich ist nicht leer...".

Das funktioniert ja auch, wobei eben hier das Problem ist, dass er nicht die ganzen Zellen der Selektion betrachtet, sondern eben nur die erste davon. Es gibt aber auch Merkmale, bei denen diese Selektion in weitere Bereiche aufgeteilt wird und dann steht zwar im geprüften Zellbereich nichts, aber im nun aufgeteilten Teil, obwohl dieser zum Gesamtbereich zählt. Und hier wird ignoriert, dass dort Inhalt steht.

Nun soll eben auch das geprüft werden, ob irgendeine Zelle aus dem Verbund einen Inhalt hat. Geht das nicht irgendwie?

Mir würde es evtl. reichen, einfach zu wissen, wie ich sicherstelle, dass jede Zelle des Bereichs auf Inhalt geprüft wird.

0
@fx8350

Aslo dein Problem ist, das deine For Schleife sofort abbricht weil du so oder so auf ein Exit function im ersten durchlauf triffst.

Hab die Funktionen mal etwas umgeschrieben

Public Function checkdeletion() As Boolean
    Dim emptySelection As Boolean: emptySelection = True
    Dim cell As Range, msg As String
    For Each cell In Selection
        emptySelection = emptySelection And IsEmpty(cell)
        If emptySelection = False Then
            msg = MsgBox("Soll das Merkmal gelöscht werden?", vbYesNo + vbQuestion, "")
            If msg = vbYes Then
                Call CriterionVar
                Call InspectionFeatures
            End If
            Exit Function
        End If
    Next cell
    MsgBox "Kein Merkmal vorhanden.", vbOKOnly + vbExclamation, ""
End Function


Public Function checkselection() As Boolean
    Dim emptySelection As Boolean: emptySelection = True
    Dim cell As Range, msg As String
    For Each cell In Selection
        emptySelection = emptySelection And IsEmpty(cell)
        If emptySelection = False Then
            msg = MsgBox("Bereich ist nicht leer!" & vbCrLf & "Fortfahren und aktuellen Eintrag überschreiben?", vbYesNo + vbQuestion, "")
            If msg = vbYes Then
                Call CriterionVar
                Call InspectionFeatures
                Call InspectionCriterion
            End If
            Exit Function
        End If
        Next
    Call CriterionVar
    Call InspectionCriterion
    checkselection = emptySelection
End Function

Diese wird aber nach wie vor nur so lange laufen, bist die ersten nicht leere Zelle gefunden wird. Evtl reicht dir das ja bereits.

1
@LtLTSmash

Wie geil ist das denn? ich zerbreche mir die ganze Zeit den Kopf und der Code war fast richtig. Es funktioniert nun. Also geht es ja doch mit verbundenen Zellen! Danke!

1
  • Ist es Absicht, dass du in der Schleife eine Messagebox aufrufst?
  • Wenn du mit Exit Function aussteigst, ist u. U. der Rückgabewert von checkdeletion nicht definiert.
  • Wenn die Funktion ganz normal bis zum Ende läuft, ist der Rückgabewert nicht definiert.
  • Der letzte Else-Zweig ergibt keinen Sinn.
  • Mit cell.MergeArea(1) kannst du wie es aussieht den Wert eines Verbundes herausfinden.

Ich weiß es doch auch nicht genau. Es hat zumindest funktioniert. Wenn die Zelle leer ist, kommt "kein Merkmal vorhanden" und wenn nicht, dann die andere Abfrage und Subs öffnen sich. Den Code habe ich im Internet gefunden und er erfüllt seinen Zweck. Nur leider erkennt er halt nicht, ob generell im selektierten Bereich etwas geschriebenes steht und genau das soll ja passieren.

0
@Suboptimierer

Hi, sorry für die späte Rückmeldung. Ich verstehe leider nicht, was dieses MergeArea machen soll und wie ich das einbinden müsste. Ich habe einen markierten Zellbereich und es soll geprüft werden, ob in einer dieser Zellen aus dem Bereich Inhalt geschrieben steht. Und wenn das so ist, soll dann entsprechend der Code ausgeführt werden.

0

Was möchtest Du wissen?