Access 2003 bietet verschiedene Möglichkeiten um Datensätze zu suchen.
Wann verwende ich welche Methode ?
Wann verwende ich Find, wann Seek, wann eine SQL-Anweisung ?
Von DLookup mal abgesehen.
Hallo;
Mit Find sucht man im Formular (über das Recordset des Formulars), Seek kenne ich nicht und SQL ist SQL, mit SQL sucht man mit der Kriteriumsklausel (Where ...).
Es kommt halt darauf an, wo Du suchst.
Seek ist ein alter Befehl der statt find genommen werden kann.
Gruß
Johann
Hallo,
seek ist kein alter Befehl!!
Die Methode SEEK ist die schnellste Methode zum Suchen von Datensätzen. Hiermit kann aber nur in Tabellen gesucht werden und das gesuchte Datenfeld muss einen eindeutigen Index besitzen. Den Indexnamen kannst du im Tabellenentwurf unter Ansicht ---> Indizes finden. Dort sind die beim Tabellenentwurf festgelegten Indizes angeführt.
Nachteilig bei Seek ist, dass die gefundenen Daten nur zur Ansicht bereit stehen und die Suche nach mehrdeutigen Indizes nicht sinnvoll ist, da die Methode kein Weitersuchen kennt. Deshalb ist die Verwendung eher selten, das heisst aber nicht, dass das ein alter Befehl ist!
Gruß Oma
Hallo Hans-Werner,
Nach Daten suchen bzw. daten selektieren ist eine der häufigsten Aufgaben in eine DB
Du hast hierzu verschiedene Möglichkeiten:
1 - Suchen und Weitersuchen mit der Methode FindRecord
2 - Suchen und Weitersuchen mit der Methode FindFirst im Recordset des Formulars
3 - Suchen mit der Methode SEEK
4 - Selektieren durch Filter im Formular setzen
5 - Selektieren im Recordset durch SQL mit WHERE-Klausel
1. Suchen: FindRecord und FindNext
Im Kopf eines Formulars legst du ein Suchfeld txtSuchfeld, ein Button cmdSuchen und ein Button cmdWeitersuchen an u. hinterlegst folgenden Code
Private Sub cmdSuchen_Click()
If IsNull(txtSuchfeld) Then Exit Sub
Me!Nachname.SetFocus
DoCmd.FindRecord Me!txtSuchfeld
End Sub
Private Sub cmdWeitersuchen_Click()
Me!txtNachname.SetFocus
DoCmd.FindNext
End Sub
Dies ist die einfachste Art für eine Suche nach einem Feld. Benutzt wird die Methode FindRecord. Die Methode verlangt, dass das Suchfeld nicht leer ist und dass das Feld, indem gesucht werden soll, im Formular sichtbar ist und den Focus besitzt. Zur Methode können weitere Parameter eingesetzt werden. Die Methode FindNext übernimmt den Suchbegriff und alle anderen gesetzten Parameter von FindRecord
2. Suchen: Find und RecordsetClone
Im Formularkopf legst du ein Kombinationsfeld cboSuchfeld und ein Button cmdWeitersuchen an
Für das Ereignis "Nach Aktualisierung" für Kombinationsfeld cboSuchfeld folgender Code:
Private Sub cboSuchfeld_AfterUpdate()
Dim rs As Recordset
Set rs = Me.RecordsetClone
rs.FindFirst "Nachname=' " & Me!cboSuchfeld & " ' "
Me.Bookmark = rs.Bookmark
End Sub
bzw. für Weitersuchen:
Private Sub bntWeitersuchen_Click()
Dim rs As Recordset
Set rs = Me.RecordsetClone
rs.FindNext "Nachname='" & Me!cboSuchfeld & "'"
If Not rs.NoMatch Then
Me.Bookmark = rs.Bookmark
Else
MsgBox "nix mehr da"
End If
End Sub
Die Methode FindRecord verlangt immer , dass das zu suchende Feld aktiviert ist. Dies ist bei der Methode Find und RecordsetClone im Einzelformular nicht der Fall.
Mit rs.FindFirst "Nachname=' " & Me!cboSuchfeld & " ' " (es wird mit Text gesucht) wird im Recordset des Formulars gesucht und nach dem Finden mit Me.Bookmark = rs.Bookmarkkönnte wird der gefundene Datensatz zum aktuellen Datensatz im Formular gemacht.
Das Suchfeld kann natürlich auch als einfaches Textfeld gestaltet sein, um auch mit Teilstrings zu suchen Dann muss allerdings mit :
Me.RecordsetClone.FindFirst "Nachname Like ' * " & Me!txtSuchfeld & " * ' " gesucht werden!
3. Suchen: SEEK
Zur Suche erstellst du ein ungebundenes Formular mit dem Textfeld txtSuchfeld und den Button cmdSuchen
Private Sub cmdSuchen_Click()
Dim db As DAO.Database, rs As DAO.Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("tblKunden", dbOpenTable)
If IsNull(Me!txtSuchfeld) Then Exit Sub
rs.Index = "idxKundenNr"
rs.Seek "=", Me!txtSuchfeld
If Not rs.NoMatch Then
Me!Firma = rs!Firma
Me!Straße = rs!Straße
Me!PLZ = rs!PLZ
Me!Ort = rs!Ort
Else
MsgBox "nix da"
End If
End Sub
4. Selektieren: Filter setzen
Im Formularkopf legst du ein Textfeld txtSuchfeld und die Button cmdFiltern und cmdAlle an
für Button Filtern mit Ereignis BeimKlicken folgender Code:
Private Sub cndFiltern_Click()
Me.Filter = "Nachname LIKE ' * " & Me!txtSuchfeld & " * ' "
Me.FilterOn = True
End Sub
bzw. für den Button bnt Alle:
Private Sub cmdAlle_Click()
Me.FilterOn = False
End Sub
Mit Me.Filter = "Nachname LIKE ' * " & Me!txtSuchfeld & " * ' " wird ein Filter mit *Nachname* gesetzt, d.h. es können auch Teilbegriffe des Namens zur Suche verwendet werden. Mit Me.FilterOn = True wird der Filter aktiviert und mit Me.FilterOn = False wieder aufgehoben.
5. Selektieren: SQL mit Where-Klausel
Im Formularkopf legst du ein Textfeld txtSuchfeld und die Button cmdAuswahl und cmdAlle an, für Button Auswahl mit Ereignis BeimKlicken folgender Code:
Private Sub cmdAuswahl_Click()
If IsNull(txtSuchfeld) Then Exit Sub
Me.RecordSource = "Select * from tblPersonal" _
& " WHERE txtNachname LIKE' * " & Me!txtSuchfeld & " * ' "
End Sub
zw. für den Button bnt Alle:
Private Sub cmdAlle_Click()
Me.RecordSource = "SELECT * From tblPersonal"
End Sub
Mit "Select * from tblPersonal WHERE txtNachname LIKE' * " & Me!txtSuchfeld & " * ' " wird direkt in der Tabelle (oder Abfrage) der Datenherkunft gesucht, und mit Me.RecordSource die Datenherkunftsquelle des Formulars bestimmt.
Diese Methode ist für häufiges Suche/Selektieren wohl die beste, da problemlos nach mehreren Feldern selektiert werden kann. Hierzu in der Anlage mal ein kleines Beispiel
Es gäbe noch so manches zu den einzelnen Methoden zu sagen, bzw. gibt es noch allerlei Tricks zur Erweiterungen der Methoden.
Ich denke aber, ich habe dir mal einen kleinen Überblick verschafft.
Gruß Oma
[Anhang gelöscht durch Administrator]
Vielen Dank für die ausführliche Antwort.
Du hast dir eine Menge Arbeit gemacht.
Konkret noch folgendes Beispiel nachgeschoben:
Ich habe eine Kundendatenbank bzw. etwas ähnliches mit Vorname, Nachname, Telefonnummer usw.
Nun möchte ich mit einem Formular (Ungebundene Felder) nach einer beliebigen Kombination aus Eingabewerten suchen können. Also nur nach dem Vornamen oder Nachnamen oder einer Kombination aus Vornamen und Nachnamen usw. Jedes einzelne Feld kann also leer sein oder auch nicht.
Momentan habe ich mir einen Suchstring zusammengebastelt und Find benutzt.
Es wird also kein Datensatz, ein Datensatz oder auch mehrere Datensätze gefunden.
Wird kein Datensatz gefunden wird eine entsprechende Meldung ausgegeben; werden mehrere Datensätze ausgegeben so wird die Anzahl der gefundenen Datensätze ausgegeben damit der Nutzer seine Suche verfeinern kann. Wird nur ein Datensatz gefunden so sollen in einem Unterformular die entsprechenen Adressen des Kunden ausgegeben werden (Können mehrere sein). Wie ich ein Unterformular in der Datenblattansicht mit mehreren Zeilen benutze ist mir auch noch nicht klar.
Die Tabelle benutzt natürlich einen Autowert als eindeutigen Index da Vorname, Nachname usw. nie eindeutig sind.
Ist der Ansatz mit dem zusammenbasteln des Suchstrings und der Verwendung von Find der beste ? ???
Man erstellt aus den gegeben Suchoptionen eine SELECT -Anweisung (also eine SQL-Abfrage) und schiebt diese in in die RecordSource des Unterformulars.
Zum Beispiel.
Dein Hauptformular enthält die Felder NachName, Vorname, Strasse, Ort
sowie ein Unterformular namens "frmKundenUF"
Du erstellst eine Routine zur Erstellung des Suchstrings:
Private Sub KundenSuchen ()
Dim strSQL as String
strSQL = "SELECT * FROM Kunden WHERE "
if Me!NachName > "" then
strSQL = strSQL & " NachName like '" & Me!NachName & "*' AND "
end if
if Me!VorName > "" then
strSQL = strSQL & " VorName like '" & Me!VorName & "*' AND "
end if
if Me!Strasse > "" then
strSQL = strSQL & " Strasse like '" & Me!Strasse & "*' AND "
end if
if Me!Ort > "" then
strSQL = strSQL & " Ort like '" & Me!Ort & "*' AND "
end if
' das WHERE oder das AND hinten abschneiden
if right$(strSQL,6) = "WHERE " then
strSQL = left$ (strSQL, len(strSQL - 6)
else
strSQL = left$ (strSQL, len(strSQL - 4)
end if
' msgbox("Die Anweisung lautet: " & strSQL)
Me.frmKundenUF.Form.RecordSource = strSQL
End Sub
Achte auf die Feinheiten: Vor den "-Zeichen sind Hochkomma ' versteckt.
Heraus kommt dann eine Anweisung wie z.B.
SELECT * FROM Kunden WHERE NachName like 'Müll*' AND Ort like 'Mann*'
Wenn Du sehen willst, enferne das Hochkomma vor der msgbox-Zeile.
Dann erstellst Du einen Button "Suchen" im Formular und rufst diese Routine auf:
Private Sub btnSuchen_Click()
KundenSuchen
End Sub
Ich hoffe, in der Routine ist kein Fehler drin, das habe ich ohne Test einfach schnell hier reingetan.
Danke, wieder was gelernt.
Du bastelst also auch einen String zusammen und verwendest dann die RecordSource Eigenschaft anstelle der Find Methode.
Noch eine Frage zur RecordSource Eigenschaft.
Wenn ich diese während des Programmablaufes ändere, wird dann das entsprechende Formular bzw. Unterformular automatisch aktualisiert ? Mit Requery funktioniert es bei mir nicht.
Als Ausschnitt (Das Formular ist bereits geöffnet):
Unterformular ausgeben, Schüler ist Index also vom Type Long
Innerhalb von With bezogen auf den Recordset
Die SQL Abfrage funktioniert
Me ist das Hauptformular, SchülerUndAdressen ist die Zwischentabelle zwischen der Tabelle Schüler und der Tabelle Adressen
Schüler = CStr(.Fields("Schüler").Value)
SQLstring = "SELECT * FROM Adressen INNER JOIN SchülerUndAdressen ON SchülerUndAdressen.Adresse = Adressen.Adresse WHERE SchülerUndAdressen.Person = " & Schüler & " ;"
Me.Schüler_Adressen_Unterformular.Form.RecordSource = SQLstring
Me.Schüler_Adressen_Unterformular.Form.Requery
Hallo Hans-Werner,
schaue dir doch mal mein Beispiel im Anhang an.
Das kannst du doch mit wenig Aufwand für deinen Fall anwenden, indem du nur die Felder Nachname und Vorname verwendest.
Vom Prinzip ist das wie der Lösungsvorschlag von Shai, nur etwas kompakter geschrieben.
Die Suchbegriffe sind in eine Extra-Formular geschrieben. Somit kannst du das Formular als "normales" Formular benutzen aber auch das Suchformular aufrufen.
Anbei noch einmal den Code zum dynamischen Erstellen eines SQL-Strings für Zahlen, Text oder Datumsfelder:
Private Sub Start_Click()
'Beispiel für dynamischer SQL-String mit Text, Zahl, Datum
Dim krit As String, strSQL As String
If Not IsNull(Me!Firma) Then krit = krit & " And Firma Like '*" & Me!Firma & "*'"
If Not IsNull(Me!Ort) Then krit = krit & " And Ort = '" & Me!Ort & "'"
If Not IsNull(Me!UmsatzVon) Then krit = krit & " AND Umsatz >=" & Me!UmsatzVon
If Not IsNull(Me!UmsatzBis) Then krit = krit & " AND Umsatz <=" & Me!UmsatzBis
If Not IsNull(Me!GründungVon) Then krit = krit & " AND DatumGründung >= " & Format(Me!GründungVon, "\#yyyy-mm-dd\#")
If Not IsNull(Me!GründungBis) Then krit = krit & " AND DatumGründung <= " & Format(Me!GründungBis, "\#yyyy-mm-dd\#")
strSQL = "SELECT * FROM tblKunden "
If krit <> "" Then strSQL = strSQL & "WHERE" & Mid(krit, 5)
Forms!Kunden!Kunden.Caption = " Auswahl Kunden"
Forms!Kunden!Kunden_UF.Form.RecordSource = strSQL
End Sub
Gruß Oma
Ja, Requery des Unterformulars erfolgt automatisch nach Veränderung der RecordSource-Eigenschaft
Hallo Shai,
bei mir erfolgt leider keine Aktualisierung des Formulars wenn ich RecordSource ändere.
Wie wird eigentlich die Tabelle auf die Felder des Formulars abgebildet ?
Was, wenn ich in dem Formular mehr oder weniger Felder habe wie in der Tabelle ?
Müssen alle Felder vorhanden sein oder genügt es wenn diese den gleichen Namen besitzen ?
Hallo Werner,
wie hast Du denn die Felder auf den Formular, als gebunden oder als ungebundene Felder?
Aufgrund deiner Fragestellung und das sich nichts aktualisiert vermute ich das die Felder ungebunden sind.
Normalerweise nimmt man gebunde Felder und die aktualisieren sich beim Zuordnen des Recordsets.
Es müssen im Form nicht alle Felder vom DS sein. Aber Achtung wenn das Formular für die Dateneingabe dient
müssen die Pflichtfelder vorhanden sein.
Hallo Oma,
ich hätte meine Antwort etwas ausführlicher schreiben sollen. Seek ist ein alter Befehl (alt heißt ja nicht
schlecht siehe Feldnamen nur mit Buchstaben und Ziffern). Wenn ich mich richtig erinnere habe ich den
Befehl schon bei einer Triumph-Adler mit Lokomotive-Basic eingesetzt.
Hallo Jonny,
hast Recht, ich habe "alt" als "nicht mehr aktuell" aufgefasst. SEEK ist eine alte und immer noch aktuelle Methode ;D!
Gruß Oma
Hallo Johnny,
der Thread wird schon etwas länger.
Möchte jedoch keinen neuen aufmachen, da ich hier so hilfreiche Antworten finde.
"Normalerweise nimmt man gebundene Felder"
Schön, schön, aber was ist normal bzw. in welchen Fällen sollte oder muß man gebundene Felder verwenden.
Soweit ich das ausprobiert habe kann ich bei gebundenen Feldern nichts eingeben.
Die dienen also nur der Ausgabe ?
Wollte eigentlich ein Formular basteln mit dem ich sowohl einen Datensatz suchen und anzeigen, löschen oder auch neu eingeben kann. Dazu muß ich nach meiner Meinung nach ungebundene Formularfelder verwenden.
Also doch nicht RecordSource verwenden sondern find ? ???
Hallo,
also ich finde, da werden sich Gedanken um des Kaisers Bart gemacht ;) 8)
und gehen an der Lösung des Problems vorbei.
Es gibt als Basis:
1) Tabellen mit Feldern bestimmter Datentypen, die Daten speichern und als Datensatzkennung ein Primärschlüsselfeld haben (sollten!)
2) Beziehungen zwischen den Tabellen, wobei diese durch die Angabe der Schlüsselfelder (Primär- und Fremdschlüssel) definiert werden.
3) Abfragen, die u. a. solche in Beziehung stehenden Tabellen zu einer "Sicht" zusammenfassen.
4) Formulare, die über ihre Eigenschaft "Datenherkunft" an eine Tabelle (oder Abfrage) "gebunden" sind , d. h. ihre Daten eben von dort beziehen.
5) In Formularen gebundene Felder (Steuerelemente), die wiederum die entspr. Feldinhalte anzeigen oder darstellen können und weil gebunden, diese auch wieder in die Datenherkunft (spriche Tabelle/Abfrage) zurückspeichern.
6) Formulare sind interaktiv, d. h. man kann Daen hinzufügen, ändern, löschen und auch die im Formular selber oder bei den einzelnen Steuerelementen auftretenden Ereignisse reagieren. (z. B: per VBA als Ereignisprozeduren).
Allein mit diesen "Objekten" kommt man schon ein ganzes Stückweit voran.
Daneben sind natürlich auch ungebundene Formulare oder auch lediglich Steuerelemente einsetzbar. Die zeigen halt, weil eben ungebunden, nicht "automatisch" irgendwelche Feldinhalte aus der Datenherkunft (die zudem ja auch nicht vorhanden sein muß) an, sondern deren Werte müssen von Hand (soll heißen per Prozedur oder durch Eintippen) eingetragen werden. Sollen diese Werte dann auch noch (irgendwo) gespeichert werden, muß das eben auch per Code geschehen, weil in diesem Fall die "Access-Automatik" halt fehlt.
Soll heißen: ungebundene Steuerelemente werden in den meisten Fällen zur Ablaufsteuerung in Formularen verwendet, z. B. Kombifelder zur Suche bestimmter Datensätze, bzw. nur als Grundlage für den Zusammenbau des u. g. SQl-Strings (Abfrage) für ein Formular.
Um nun diese Datensätze zu finden, können die angesprochenen Methoden benutzt werden. Meistens ist es aber nur:
SQL-String mit Where-Condition für die Datenherkunft in einem Formular. Dadurch werden NUR die Datensätze aus der Tabelle gelesen, die den Kriterien entsprechen.
Filter-Methode des Formulares: Damit werden die schon dem Formular vorher angebotenen Datensätze lediglich für die Anzeige eingeschränkt. Ein Abfrage (Auslesen aus) der Tabelle erfolgt dabei nicht mehr.
Fast alles über Formulare Gesagtes gilt auch für Berichte, nur dass Berichte nicht interaktiv sind..(Keine Daten über die gebundenen Felder eingebbar sind und ändern können.
Seek ist wie gesagt weniger üblich in der Access-Umgebung.
Hallo HansWerner,
ich muss Franz rechtgeben; um was geht es denn nun?
Zitat"Normalerweise nimmt man gebundene Felder"
Schön, schön, aber was ist normal bzw. in welchen Fällen sollte oder muß man gebundene Felder verwenden.
1. Normal ist eben, gebundene Felder zu benutzen, damit kann man in einfachster Weise Daten eingeben/ändern/ansehen; ungebundene eben für Suchfelder u.ä.
2. Wenn du Daten mit Kriterien für verschiedene Felder (z.B. Nachname und/oder Vorname) suchen willst, dann ist die Erstellung eines dynamischn SQL-Strings eben das geeigneste.
Ich hatte dazu in meinem 2. Beitrag ein kleines Beispiel als Anhang dargestellt.
Hier hast du ein "normales" Formular, in dem du anfügen, ändern bzw. löschen u. gleichzeitig durch das Aufrufen eines zusätzlichen Suchformulars nach verschiedenen Feldern selektieren kannst.
Was willst du eigentlich mehr???
Gruß Oma