Alternative für After := ActiveCell bei der Suche in einem Range-Objekt
#1
Hallo zusammen,

mit unten angegebenem  Beispielcode kann ich über die Range(Bereich).Find - Methode das Wort "ABC" finden. Mein Problem ist, dass ich die zweite Fundstelle von"ABC"
erst mit select auswählen muss (Range("A1:A15").Find("ABC").Select) und dann mit after:=ActiveCell weitermachen kann.

Warum kann ich nicht nach der esten Fundstelle für After := "$A$6" setzen? Was mache ich syntaktisch falsch?



Code:
Sub Finden_Mit_Range()
Dim Feld
Feld = Array(1, 2, 3, 4, 5, "ABC", 7, 8, 9, "ABC", 11, "ABC", 13, "ABC", 14, 15)

Range("A1:A16").value = Application.Transpose(Feld)

Debug.Print Range("A1:A15").Find("ABC").Address

'Finden mit ActiveCell geht:
Range("A1:A15").Find("ABC").Select
Debug.Print Range("A1:A15").Find("ABC", after:=ActiveCell).Address

'Geht nicht!!!
Debug.Print Range("A1:A15").Find("ABC", after:="$A$6").Address

End Sub
Top
#2
Hallo Christa!
dafür gibt es neben Range.Find Range.FindNext
Die VBA-Hilfe liefert ein anschauliches Beispiel:
Code:
With Worksheets(1).Range("a1:a500")
   Set c = .Find(2, lookin:=xlValues)
   If Not c Is Nothing Then
       firstAddress = c.Address
       Do
           c.Value = 5
           Set c = .FindNext(c)
       Loop While Not c Is Nothing And c.Address <> firstAddress
   End If
End With

Gruß Ralf
Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. 
Lehre einen Mann zu fischen und du ernährst ihn für sein Leben. (Konfuzius)
[-] Folgende(r) 1 Nutzer sagt Danke an RPP63 für diesen Beitrag:
  • ChristaRohn
Top
#3
... das Ganze mal auf Dein spezielles Problem angepasst:

Modul Modul1
Option Explicit 
 
Sub Finden_Mit_Range() 
Dim Feld, rngC As Range, FirstAddress As String 
Feld = Array(1, 2, 3, 4, 5, "ABC", 7, 8, 9, "ABC", 11, "ABC", 13, "ABC", 14, 15) 
With Range("A1:A16") 
   .Value = Application.Transpose(Feld) 
   Set rngC = .Find("ABC", LookIn:=xlValues) 
   If Not rngC Is Nothing Then 
       FirstAddress = rngC.Address 
       Do 
          Debug.Print rngC.Address 
          Set rngC = .FindNext(rngC) 
       Loop While Not rngC Is Nothing And rngC.Address <> FirstAddress 
   End If 
End With 
End Sub 
Gruß Ralf
Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. 
Lehre einen Mann zu fischen und du ernährst ihn für sein Leben. (Konfuzius)
[-] Folgende(r) 1 Nutzer sagt Danke an RPP63 für diesen Beitrag:
  • ChristaRohn
Top
#4
@Christa,

deine Aufgabe kann auch sehr gut rekursiv gelöst werden.


Code:
Function Rekursiv(FirstAddress As Variant, nextAddress As Variant)
If Not nextAddress = FirstAddress Then
Debug.Print nextAddress
Call Rekursiv(FirstAddress, Range("A1:A15").Find("ABC", Range(nextAddress)).Address)
End If
End Function


Sub Demo_Range_Find_Methode()
On Error GoTo Errorhandler
Dim Feld, FirstAddress
Range("A1").Activate
Feld = Array(1, 2, 3, 4, 5, "ABC", 7, 8, 9, "ABC", 11, "ABC", 13, "ABC", 14, 15)
Range("A1:A16").value = Application.Transpose(Feld)

FirstAddress = Range("A1:A15").Find("ABC").Address
Debug.Print Range("A1:A15").Find("ABC").Address
Call Rekursiv(FirstAddress, Range("A1:A15").Find("ABC", Range(FirstAddress)).Address)

Errorhandler:
End Sub
Top
#5
Hi!
Einigen wir uns darauf, dass wir LookAt:=xlWhole nicht explizit angegeben haben, obwohl empfehlenswert?
Ansonsten dreht Deine Rekursion zwei Leerrunden, warum auch immer.
Ich mag rekursive Algorithmen, wenn nötig.  :21:

Ach so: Feedback geht Christa seit geraumer Zeit aAv

Gruß Ralf
Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. 
Lehre einen Mann zu fischen und du ernährst ihn für sein Leben. (Konfuzius)
Top
#6
Hallo Ralf,
die von dir angesprochenen Leerrunden bei der Rekursion verstehe ich nicht. Bedenke, die Anzahl der Selbstaufrufe der Funktion bei der Rekursion entspricht auch
der Anzahl wie oft der Compiler bei F8 im Einzelschrittmodus zwischen End If und End Function hin- und herspringt.

Ansonsten hier noch eine Alternativlösung ohne Rekursion. Bei der verschachtelten Version kommt man mit nur 6 Programmzeilen aus.

Code:
Sub Finden_Mit_Range_ohne_Rekursion()
On Error Resume Next
Dim Feld, NextAddress, FirstAddress
Range("A1").Activate
Feld = Array(1, 2, 3, 4, 5, "ABC", 7, 8, 9, "ABC", 11, "ABC", 13, "ABC", 14, 15)
Range("A1:A16").value = Application.Transpose(Feld)

'Verkürzte verschachtelte Version
Debug.Print Range("A1:A15").Find("ABC").Address
NextAddress = Range(Range("A1:A15").Find("ABC").Address).Offset(1, 0).Address
While Not Range("A1:A15").Find("ABC", Range(NextAddress)).Address = Range("A1:A15").Find("ABC").Address
Debug.Print Range("A1:A15").Find("ABC", Range(NextAddress)).Address
NextAddress = Range("A1:A15").Find("ABC", Range(NextAddress)).Address
Wend

'Normal
FirstAddress = Range("A1:A15").Find("ABC").Address
Debug.Print Range("A1:A15").Find("ABC").Address
NextAddress = Range(FirstAddress).Offset(1, 0).Address
While Not Range("A1:A15").Find("ABC", Range(NextAddress)).Address = FirstAddress
Debug.Print Range("A1:A15").Find("ABC", Range(NextAddress)).Address
NextAddress = Range("A1:A15").Find("ABC", Range(NextAddress)).Address
Wend

End Sub
Top
#7
Hallo

ich sehe eine Menge Antworten, manche so komplex das ich Zeit brauche sie zu verstehen.

Es fehlt aber eine einfache Antwort auf die konkret gestellte Frage:  Warum geht es nicht?
Nach After muss der Bereich entweder so:  [A6] oder als Range("A6") angegeben werden.
Dann klappt auch de Original Code. Die Adresse muss innerhalb von "A1:A15" sein.   

Debug.Print Range("A1:A15").Find("ABC", after:="$A$6").Address

mfg
Top
#8
Hi!
Du hast ja Recht, Gast.
After:= benötigt nun mal ein Range-Objekt.
Aber:
Konkret auf das Beispiel des TE angewandt, wird es eher unübersichtlicher als die .FindNext-Methode.

Modul Modul1
Option Explicit 
 
Sub Finden_Mit_Range() 
Dim Feld, firstMatch As Range, nextMatch As Range 
Feld = Array(1, 2, 3, 4, 5, "ABC", 7, 8, 9, "ABC", 11, "ABC", 13, "ABC", 15, 16) 
 
With Range("A1:A16") 
   .Value = Application.Transpose(Feld) 
   Set firstMatch = .Find("ABC", Cells(1), xlValues, xlWhole) 
   If Not firstMatch Is Nothing Then 
      Debug.Print firstMatch.Address 
      Set nextMatch = .Find("ABC", firstMatch, xlValues, xlWhole) 
      If firstMatch.Address = nextMatch.Address Then Exit Sub 
      Do 
         Debug.Print nextMatch.Address 
         Set nextMatch = .Find("ABC", nextMatch, xlValues, xlWhole) 
      Loop While Not nextMatch Is Nothing And firstMatch.Address <> nextMatch.Address 
   End If 
End With 
Set firstMatch = Nothing 
Set nextMatch = Nothing 
End Sub 

Gruß Ralf
Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. 
Lehre einen Mann zu fischen und du ernährst ihn für sein Leben. (Konfuzius)
Top
#9
@Gast123

Hallo Gast 123,
du hast völlig Recht. Die Beantwortung einer Frage sollte so einfach und klar wie möglich gestaltet sein, damit jedes Forumsmitglied und jeder Gast
die Angelegenheit so schnell und einfach wie möglich versteht.

Nachdem, die erste Fundstelle "$A$6" gefunden worden ist, sucht man die nächste Fundstelle einfach, indem man für After Range("$A$6") setzt!
Falls du noch Fragen hast: Nur zu!


Code:
Sub Finden_Mit_Range()
Dim Feld
Feld = Array(1, 2, 3, 4, 5, "ABC", 7, 8, 9, "ABC", 11, "ABC", 13, "ABC", 14, 15)

Range("A1:A16").value = Application.Transpose(Feld)

Debug.Print Range("A1:A15").Find("ABC").Address
'Nächste Fundstelle, einfach für After Range("$A$6") setzen!
Debug.Print Range("A1:A15").Find("ABC", Range("$A$6")).Address

End Sub
Top
#10
@Ralf

Zitat:Ach so: Feedback geht Christa seit geraumer Zeit aAv

Was soll ich machen? Ich hatte bereits bei Dir auf den Danke Button gedrückt und mit dem "ratrad" Code wußte ich dann auch , dass ich die Zelladresse in ein Range "einpacken" mußte.

Für mich war die Sache damit erledigt.

Christa
Top


Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 2 Gast/Gäste