Neuigkeiten:

Wenn ihr euch für eine gute Antwort bedanken möchtet, im entsprechenden Posting einfach den Knopf "sag Danke" drücken!

Mobiles Hauptmenü

Aufforderung für Parametereingabe für Anhang

Begonnen von KonradR, September 19, 2024, 16:27:06

⏪ vorheriges - nächstes ⏩

KonradR

Hallo liebe Accessfreunde,

ich habe eine Accesdatenbank mit einer Abfrage und einem Formular erstellt, dass auf dieser Abfrage beruht.
Nun habe ich im Formular ein ungebundenes Textfeld eingefügt und möchte, je nach dem was ich Textfeld eingebe, dass im Formular nach dem Inhalt gefiltert wird. Es mir also nur die Datensätze anzeigt, die den entsprechend eingegebenen Text im Textfeld enthalten. Das habe ich so gelöst:
Private Sub txtSuchen_Change()
Dim SQL As String
Dim strSuchtext As String

strSuchtext = Forms("frm010Kommunikation").Controls("txtSuchen").Text

SQL = "SELECT * FROM qryVorgangFirmaAnsprechpartner WHERE tblVorgang.VorgaInhalt LIKE """ & "*" & strSuchtext & "*" & """"

'Debug.Print SQL

Forms("frm010Kommunikation").Controls("sfrmVorgang").Form.RecordSource = SQL
Forms("frm010Kommunikation").Controls("sfrmVorgang").Requery
End Sub


Mein Problem aktuell ist, dass folgende Aufforderung auftaucht, sobald ich ein Zeichen in das Textfeld eingebe:
Sie dürfen in diesem Board keine Dateianhänge sehen.

Hier ist noch ein Bildschirmfoto von der Abfrage:
Sie dürfen in diesem Board keine Dateianhänge sehen.


Es scheint also ein Problem mit dem Anhang zu sein. Habt ihr da Idee, wo ich hier näher bei der Fehlersuche ansetzen kann? Aktuell habe ich, außer das es mit dem Anhang zu tun hat, keine Idee.
Schon im Voraus vielen Dank.

Beaker s.a.

Hallo Konrad,

Ich bin mir zwar nicht ganz sicher, aber ich denke, dass du dich
in der WHERE-Klausel auch auf die Query beziehen musst
SQL = "SELECT * FROM qryVorgangFirmaAnsprechpartner WHERE qryVorgangFirmaAnsprechpartner.VorgaInhalt LIKE """ & "*" & strSuchtext & "*" & """"Wenn es in der Query das Feld "VorgaInhalt" nicht gibt, musst du
die Query und die Table über ein geeignetes Feld joinen, um mit dem
Feld aus der Table zu filtern.

gruss ekkehard
Alles, was geschieht, geschieht. - Alles, was während seines Geschehens etwas anderes geschehen lässt, lässt etwas anderes geschehen. - Alles, was sich selbst im Zuge seines Geschehens erneut geschehen lässt, geschieht erneut. - Allerdings tut es das nicht unbedingt in chronologischer Reihenfolge.
(Douglas Adams, Mostly Harmless)

Bitsqueezer

Hallo,

Du liebst es maximal umständlich, hm?... ;)

Versuch's mal so:
Private Sub txtSuchen_Change()
    Dim strSQL      As String
    Dim strSuchtext As String

    strSuchtext = Me.txtSuchen.Text

    strSQL = "SELECT qVFA.* FROM qryVorgangFirmaAnsprechpartner AS qVFA " & _
             " WHERE qVFA.VorgaInhalt LIKE '*" & strSuchtext & "*'"

    'Debug.Print strSQL

    With Me.sfrmVorgang.Form
        .RecordSource = strSQL
        .Requery
    End With
End Sub

Du kannst nicht auf den Prefix "tblVorgang" zugreifen, da Du Daten aus einer Abfrage beziehst, es existiert also nur der Name der Query, den man dazu mit einem Alias abkürzt.

Gruß

Christian

Knobbi38

#3
Es wäre natürlich hilfreich, wenn man den SQL-Code von "qryVorgangFirmaAnsprechpartner" kennen würde, da das bemängelte Feld ein MultiValueField ist.

Außerdem ist es sicherlich einfacher und besser, die Filter-Eigenschaft des Formulars zu verwenden, als ständig die Recordsource neu zu setzen.

Gruß Ulrich
 


KonradR

Hallo  Beaker s.a.,

vielen Dank für deine Antwort.
Deinen Kode:
Zitat von: Beaker s.a. am September 19, 2024, 16:59:38SQL = "SELECT * FROM qryVorgangFirmaAnsprechpartner WHERE qryVorgangFirmaAnsprechpartner.VorgaInhalt LIKE """ & "*" & strSuchtext & "*" & """"

Habe ich probiert. Das funktioniert leider auch nicht und ergibt die gleiche Fehlermeldung.

Zitat von: Beaker s.a. am September 19, 2024, 16:59:38Wenn es in der Query das Feld "VorgaInhalt" nicht gibt
Das Feld gibt es tatsächlich.


KonradR

Hallo Bitsqueezer,

Zitat von: Bitsqueezer am September 19, 2024, 17:02:03Du liebst es maximal umständlich, hm?... ;)
Ich denke schon. Ich denke wahrscheinlich noch nicht genug VBA.
Zitat von: Bitsqueezer am September 19, 2024, 17:02:03Versuch's mal so:
Code [Auswählen] Erweitern
Private Sub txtSuchen_Change()
    Dim strSQL      As String
    Dim strSuchtext As String

    strSuchtext = Me.txtSuchen.Text

    strSQL = "SELECT qVFA.* FROM qryVorgangFirmaAnsprechpartner AS qVFA " & _
             " WHERE qVFA.VorgaInhalt LIKE '*" & strSuchtext & "*'"

    'Debug.Print strSQL

    With Me.sfrmVorgang.Form
        .RecordSource = strSQL
        .Requery
    End With
End Sub
Das funktioniert leider auch nicht. Dein Vorschlag hat mich aber auf die Idee gebracht, den SQL-Code der Abfrage in den VBA-Editor zu kopieren. Das sieht dann so aus:
Private Sub txtSuchen_Change()
Dim SQL As String
Dim strSuchtext As String

'strSuchtext = Forms("frm010Kommunikation").Controls("txtSuchen").Text
strSuchtext = Me.txtSuchen.Text

'SQL = "SELECT * FROM qryVorgangFirmaAnsprechpartner WHERE qryVorgangFirmaAnsprechpartner.VorgaInhalt LIKE """ & "*" & strSuchtext & "*" & """"
'strSQL = "SELECT qVFA.* FROM qryVorgangFirmaAnsprechpartner AS qVFA WHERE qVFA.VorgaInhalt LIKE '*" & strSuchtext & "*'"
SQL = "SELECT tblVorgang.VorgaID, tblVorgang.VorgaProjeIDRef, tblVorgang.VorgaDatum, tblVorgang.VorgaZeit, tblVorgang.VorgaKontaArtIDRef, " & _
        "tblVorgang.VorgaKoOrtIDRef, tblVorgang.VorgaGewerkIDRef, tblVorgang.VorgaThema, tblVorgang.VorgaInhalt, tblVorgang.VorgaAnsprEinsIDRef, " & _
        "tblVorgang.VorgaAnsprZweiIDRef, tblKontakt.KontaFirmaIDRef, tblKontakt.KontaAnspaIDRef, tblKontakt_1.KontaFirmaIDRef, tblKontakt_1.KontaAnspaIDRef, " & _
        "tblVorgang.VorgaAnhang, tblVorgang.VorgaAnhang.FileName FROM tblKontakt INNER JOIN (tblVorgang INNER JOIN tblKontakt AS tblKontakt_1 " & _
        "ON tblVorgang.VorgaAnsprZweiIDRef = tblKontakt_1.KontaID) ON tblKontakt.KontaID = tblVorgang.VorgaAnsprEinsIDRef WHERE " & _
        "(((tblVorgang.VorgaThema) Like '*" & strSuchtext & "*'" & "))ORDER BY tblVorgang.VorgaID;"

Debug.Print SQL

With Me.sfrmVorgang.Form
        .RecordSource = strSQL
        .Requery
    End With
End Sub


Das funktioniert dann. Ich weis zwar nicht warum. Aber es geht. Habt ihr da evtl eine Idee?


KonradR

Hallo  knobbi38,

Zitat von: knobbi38 am September 19, 2024, 20:34:07Es wäre natürlich hilfreich, wenn man den SQL-Code von "qryVorgangFirmaAnsprechpartner" kennen würde, da das bemängelte Feld ein MultiValueField ist.
Den SQL-Code habe ich in meiner letzten Nachricht beigefügt.

Zitat von: knobbi38 am September 19, 2024, 20:34:07Außerdem ist es sicherlich einfacher und besser, die Filter-Eigenschaft des Formulars zu verwenden, als ständig die Recordsource neu zu setzen.
Ok. Was konkret, im Code und evtl. in der Rechengeschwindigkeit und anderen Dingen, die ich jetzt nicht sehe, macht es denn einfacher und besser als die Recordsetsource ständig neu zu setzen?

Bitsqueezer

Hallo,

mal abgesehen davon, daß es so nicht funktionieren kann, da Du aus "strSQL" wieder "SQL" gemacht hast (sollte man vermeiden wg. Konflikt mit bestehenden namen wie QueryDef.SQL) und unten als RecordSource immer noch strSQL zuweist...

Du hast einfach nur den SQL-Code übernommen, ohne mal entsprechend Aliase zu vergeben, was den Code schon mal immens kürzt. Auch fügst Du das "ORDER BY" wieder als getrennten String hinzu - warum? Am Ende soll alles in einem String landen.

Bei Attachment-Fields könnte ich mir ebenfalls Probleme vorstellen. Ich würde sie, genau wie Multi Valued Fields (die Ulrich anführte, was es hier aber nicht ist), unbedingt vermeiden. Einerseits ist es wieder so eine "Access-Spezialkonstruktion", die nur mit Problemen behaftet ist, andererseits sollte man grundsätzlich keine Dateien in der Datenbank speichern, da es die Datenbankdatei sehr schnell stark anwachsen läßt, die 2GB-Grenze ist dann schnell erreicht. Besser nur Pfad-/Dateiname speichern und die Datei im Dateisystem belassen.

Da das Feld "VorgaThema" ja in der Originalabfrage drin war (wenn Du es nicht hier im SQL-Code hinzugefügt hast), sollte die Abfrage auch wie vorgeschlagen funktionieren. Natürlich nur, wenn Du nicht weiterhin nach "tblVorgang.VorgaThema" abgefragt hast in der LIKE-Klausel. Wegen der Besonderheit des Feldtyps kann ich das aber nicht genau sagen, ich nutze solche Access-Kapriolen nicht.

Gruß

Christian

Knobbi38

@Bitsqueezer
du hast natürlich recht, ich meinte eigentlich auch ein Attachment-Field und kein MVF, welche im Prinzip aber beide auf dem gleiche DAO.Field2 Objekt beruhen, nur mit unterschiedlichen Typ-Angaben.

Hallo,
ob die Verwendung der Filter-Property Performancevorteile bringt, kann ich dir nicht sagen, aber zumindest überläßt du dem Formular selber die interne optimale weitere Verarbeitung der Daten inkl. des Caches.
Unabhängig davon sollte nach der Zuweisung einer neuen Recordsource kein weiteres Requery notwendig sein.




Beaker s.a.

Hallo Konrad,
Warum es eigentlich so nicht gehen dürfte hat Christian schon erklärt.
Mit der richtigen Variablen funzt das auch.

@christian
Ich hatte in meiner Antwort bewusst auf den Alias verzichtet, um es Konrad
einfacher zu machen es zu verstehen. Denn, wie man an seinem Code sieht, hat/
hätte er den Sinn eines solchen eh nicht verstanden.
@Konrad
Das mit dem Alias solltest du aber lernen. Und zusammen mit einer ordentlichen
Formatierung des SQL-Strings wirst du sehen, wie einfach die dann zu lesen und
zu analysieren sind.
Zitatob die Verwendung der Filter-Property Performancevorteile bringt, kann ich dir nicht sagen
Ich jetzt auch nicht. Aber das Change-Ereignis ist da m.E. unglücklich gewählt.
Bei jedem eingegebenen Zeichen wird die RecordSource neu berechnet
(inkl. autom. Requery) und dann explizit noch mal aktualisiert, - das kann
dauern. Das passiert beim Filtern aber auch
Me.Filter = "VorgaInhalt LIKE '*" & strSuchtext & "*'"
Me.FilterOn = True    'autom. Requery
'das nachfolgende ist somit obsolet (s. Hinweis von Ulrich)
Ich würde das Ereignis "After_Update" bevorzugen bzw. gleich ein Kombi in
Erwägung ziehen.

gruss ekkehard
Alles, was geschieht, geschieht. - Alles, was während seines Geschehens etwas anderes geschehen lässt, lässt etwas anderes geschehen. - Alles, was sich selbst im Zuge seines Geschehens erneut geschehen lässt, geschieht erneut. - Allerdings tut es das nicht unbedingt in chronologischer Reihenfolge.
(Douglas Adams, Mostly Harmless)

KonradR

Hallo Bitsqueezer,

Zitat von: Bitsqueezer am September 20, 2024, 10:38:57mal abgesehen davon, daß es so nicht funktionieren kann, da Du aus "strSQL" wieder "SQL" gemacht hast (sollte man vermeiden wg. Konflikt mit bestehenden namen wie QueryDef.SQL) und unten als RecordSource immer noch strSQL zuweist...
Stimmt absolut. Ich hatte dein With-Klausel hier eingefügt, aber ein meinem Kode keine With-Klausel. Daher ist auch noch dein Variablenvorschlag mit "strSQL" drin. Ich hatte meine Konstruktion mit controls... gelassen und wollte da einfach keine Angriffsfläche bieten

Zitat von: Bitsqueezer am September 20, 2024, 10:38:57Du hast einfach nur den SQL-Code übernommen, ohne mal entsprechend Aliase zu vergeben, was den Code schon mal immens kürzt. Auch fügst Du das "ORDER BY" wieder als getrennten String hinzu - warum? Am Ende soll alles in einem String landen.
Den SQL-Code habe ich einfach ungekürzt übernommen, weil das einfach ist und ich die Version mit den Aliasen noch nicht kannte. In Zukunft werde ich damit arbeiten. Das "ORDER BY" als getrennten String hinzufügen ist unnötig. Das habe ich behoben.

Zitat von: Bitsqueezer am September 20, 2024, 10:38:57andererseits sollte man grundsätzlich keine Dateien in der Datenbank speichern, da es die Datenbankdatei sehr schnell stark anwachsen läßt, die 2GB-Grenze ist dann schnell erreicht. Besser nur Pfad-/Dateiname speichern und die Datei im Dateisystem belassen.
Danke für den Hinweis. Das schaue ich mir als nächstes an.

Zitat von: Bitsqueezer am September 20, 2024, 10:38:57Da das Feld "VorgaThema" ja in der Originalabfrage drin war (wenn Du es nicht hier im SQL-Code hinzugefügt hast), sollte die Abfrage auch wie vorgeschlagen funktionieren. Natürlich nur, wenn Du nicht weiterhin nach "tblVorgang.VorgaThema" abgefragt hast in der LIKE-Klausel. Wegen der Besonderheit des Feldtyps kann ich das aber nicht genau sagen
Danke. Durch deine Antwort habe ich herausgefunden, dass ich nach "VorgaThema" und nicht nach "VorgaInhalt" gefiltert habe, was ich eigentlich wollte. Das habe ich nun auch behoben.




KonradR

Zitat von: knobbi38 am September 20, 2024, 11:28:33Unabhängig davon sollte nach der Zuweisung einer neuen Recordsource kein weiteres Requery notwendig sein.
Danke. Dann werde ich es mal ohne das Requery probieren.

KonradR

Zitat von: Beaker s.a. am September 20, 2024, 12:08:07Ich jetzt auch nicht. Aber das Change-Ereignis ist da m.E. unglücklich gewählt.
Danke, aber es soll ja bei jedem Tastaturanschlag die Auswirkung auf die Filterung der Datensätze sichtbar sein, so dass ich immer sehen kann ab wann welche Datensätze verschwinden, bzw. wieder auftauchen. Damit kann ich das gewünschte Stichwort schneller finden.

MzKlMu

Hallo,
ZitatDamit kann ich das gewünschte Stichwort schneller finden.
Da wäre ein Kombifeld mit den Stichworten als Datenherkunft aber deutlich einfacher.
Zum einen zeigt dann das Kombi nur Stichworte an die es auch gibt und zum anderen aktualisiert sich die Auswahl eines Kombis bei jedem Tastendruck automatisch (ohne Programmierung/VBA). Du bist dann sehr schnell und einfach beim gewünschten Stichwort.
Gruß Klaus

Bitsqueezer

Hallo,

@Beaker: Ich hatte Dich auch gar nicht gemeint... :)
@Ulrich: War mir schon klar, daß Du das weißt und es nur ein Flüchtigkeitsfehler war..:)

Filter: Naja, es gibt keine absolute Regel dafür, da Access das je nach Backend anders handhabt. Tatsächlich kann es performanter sein, komplett neu abzufragen, was definitiv den Vorteil hat, daß der User den Filter, den man per VBA setzt, nicht selbst herausnehmen kann, z.B. über die Datensatznavigation durch Klick auf "Gefiltert". Beim manuellen Herausnehmen des Filters bekommt VBA das erst mal nicht mit, was dann zu Unstimmigkeiten mit dem Code führen kann. Per "Form_ApplyFilter" kann man das abfangen, muß aber alles extra programmiert werden. Wenn man die RecordSource ändert, existieren die anderen Datensätze ganz einfach gar nicht und entsprechend weniger Daten werden auch übertragen. Wenn man filtert, muß das Recordset zumindest alle Daten enthalten, um es filtern zu können (mit ggf. einer Vorauswahl). Man kann nicht filtern, was nie im Recordset war. Entsprechend kann eine Neuabfrage schneller sein, wenn dadurch weniger Daten übertragen werden müssen.

Das relativiert sich allerdings, wenn man das in einem Change-Event macht. Die Verlockung ist natürlich groß, aber es geht enorm auf die Performance, weil mit JEDEM eingegebenen Zeichen wieder neu gesucht wird. Da hier auch noch mit LIKE und "*" davor und danach gesucht wird, kann auch kein Index verwendet werden, also ist Tablescan angesagt.
Der Weg von Klaus ist auch machbar - einfach eine Kombobox, die verhält sich bereits so, mit jedem Zeichen ein Autocomplete, ohne zusätzliche Abfragen. Auch hier muß man aber bedenken, daß eine große Anzahl Einträge zu Problemen führen kann. Die Kombobox kann nicht unendlich viele Einträge aufnehmen. Die Kombobox hat außerdem den Nachteil, immer das erste gefundene zu verwenden, wenn man tippt. Wenn man 2 Einträge mit "Meier" in einer Namensliste vorliegen hat, mit je einer anderen PersonenID, dann gibt die Kombobox bei Tastatureingabe nur den ersten wieder, Den nächsten muß man dann aus der Dropdownliste explizit auswählen. Außerdem funktioniert die Suche nur "ab Anfang", also nicht mit Namen mittendrin in einem Text.

Es gibt auch andere Varianten, z.B. erst nach der Eingabe des 3. Zeichens die Suche zu starten.

Ich würde allerdings auch besser "AfterUpdate" verwenden, weil dann einfach nur einmal gesucht wird. Der User kann trotzdem Zwischenergebnisse holen, wenn er will, indem er einfach weniger eingibt.

ZitatIch hatte meine Konstruktion mit controls... gelassen und wollte da einfach keine Angriffsfläche bieten
Meistens macht es mehr Sinn, den echten Code zu zeigen, statt "für's Forum" etwas abzuspecken oder total zu verändern. Probleme lassen sich dann auch erkennen.
Die Konstruktion mit Controls und Forms hat den Nachteil, daß sie nicht compilersicher ist. Der Compiler prüft keine Namen in Anführungszeichen. Bei der Schreibweise mit "Me." bekommst Du bereits von IntelliSense Unterstützung und der Compiler überprüft danach auch noch, ob Du einen Schreibfehler in Controlnamen hast. Abgesehen von dem deutlich kürzeren und einfacher lesbaren Code.

SQL-Text im Code: Wo immer machbar, solltest Du das vermeiden. Bei Access ist es nicht problematisch, da Access immer nur einen SQL-Befehl ausführen kann. Solltest Du jemals einen DB-Server als Backend verwenden, ist ein Suchfeld, dessen Eingabe in einen SQL-String eingebaut wird, gefundenes Fressen für Hacker, Stichwort "SQL-Injection". Man beendet den SQL-Befehl mit ";" und fügt dann einen neuen hintendran.Mal so als einfaches Beispiel.

Ganz nebenbei ist so ein SQL-Code in VBA dann auch schwierig zu debuggen.

Es ist daher besser, parametrisierte Abfragen zu verwenden oder Abfragen, die sich Vergleichswerte selbst aus dem Formular holen.
Auch hier gibt es wieder den Nachteil, wenn man Formular/Controlreferenzen direkt in eine Abfrage einfügt. Die Abfrage läuft dann nur, solange das Formular geöffnet ist. Das kann man wiederum vermeiden, indem man eine Public Function in einem Standardmodul einsetzen, die dann für das Holen der Eingabewerte verantwortlich ist, die wiederum testen kann, ob ein Formular geladen ist und das Feld Inhalt hat usw.

Es gibt immer viele Möglichkeiten...

Gruß

Christian