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 ⏩

Knobbi38

@christian:

Wie immer ein paar tolle Hinweise, aber zwei kleine Anmerkungen hätte ich noch:

1. Wenn man in einem Formular die AllowFilters-Eigenschaft auf FALSE setzt, kann ein Anwender nicht mehr einen per VBA gesetzten Filter manuell ändern oder löschen; das gefiltert worden ist, wird auch nicht mehr angezeigt. Es muß dann auch nichts mehr extra programmiert werden.

2.
ZitatWenn 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.
Wenn man die Recordsource ändert, müssen immer alle DS übertragen werden, erst dann kann lokal entschieden werden, welche DS relevant sind und dann wird damit der Cache gefüllt. Wenn ich mich recht erinnere, werden dabei aber nicht blind alle Daten eines DS sofort geladen, sondern nur relevante Daten. Die vollständigen Daten werden dann später asynchron nachgeladen. Ohne es jetzt aber genau zu wissen nehme ich mal an, daß Access eine Filterbedingung ähnlich wie eine Where-Condition abarbeitet, möglicherweise dabei aber mit Hilfe des Caches etwas mehr optimieren kann. Beim Setzen einer neuen Recordsource muß zwangsläufig der Cache ungültig gemacht werden.

Vielleicht hat jemand ja mal so etwas auf der Verbindungsebene aufgezeichnet und kann hier näheres dazu berichten?

Insgesamt stimme ich dir aber zu. So eine dynamische Suchfunktion belastet die Datenverbindung enorm.

Als Ergänzung vielleicht noch eine andere Möglichkeit:
Um so etwas umzusetzen habe ich einfach mal die zu durchsuchenden Datenfelder komplett in ein Array geladen, per Quicksort sortiert und dann in eine Listbox geladen. Mit dem Change-Event wird dann per Binarysearch lokal in dieser Listbox gesucht und entsprechend positioniert, so daß man das Suchergebnis inklusive dem "Trefferumfeld" sehen kann. Wenn die Daten relativ wenig verändert werden, funktioniert das auch bei sehr "langsamen" Verbindungen selbst bei einer größeren Anzahl von DS ( > 30.000 ) sehr effizient.

Gruß Ulrich




Beaker s.a.

Hallo Christian,

Hatte ich auch nicht so verstanden. Meine Einlassung sollte mehr
so eine Einleitung für den Hinweis an Konrad sein.

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 MzKlMu,

Zitat von: MzKlMu am September 20, 2024, 17:07:58Da wäre ein Kombifeld mit den Stichworten als Datenherkunft aber deutlich einfacher.
Vielleicht. Nur ist ein Kombinationsfeld deutlich kleiner als ein Textfeld (Zumindest im Normalfall). Ich will ja nach einem Ganzen Text suchen, in dem der gesuchte Wortschnippsel enthalten ist. Was ich in der Datenbank hinterlege, sind ja Gesprächsnotizen und die beschränken sich ja nicht auf einzelne Wörter sondern auf ein paar Sätze. Wenn ich nach einem Stichwort suche, will ich natürlich die Worte drumherum sehen um den Kontext und die Relevant besser erkennen zu können. Das geht mit einem Kombinationsfeld, dass nach meinem dafürhalten nur für das anzeigen einzelner Wörter oder Zahlen gedacht ist, nur bedingt.

KonradR

Hallo Bitsqueezer,

Zitat von: Bitsqueezer am September 20, 2024, 21:46:01Filter: 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.
Du meinst, einen SQL-String in VBA zu erstellen und dann der Recordsource Eigenschaft des Steuerelements zuzuweisen?

Zitat von: Bitsqueezer am September 20, 2024, 21:46:01Per "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.
Das heißt, ich kann nur mit "Form_ApplyFilter" das manuelle Ändern des Filters durch den Nutzer unterbinden und sonst nicht?

Zitat von: Bitsqueezer am September 20, 2024, 21:46:01also ist Tablescan angesagt
Tablescan heißt ja, dass alle bzw. die meißten Daten einer Tabelle durchsucht werden. Es wird doch aber nur in einem Feld eines jeden Datensatzes gesucht. Das ist, meiner Ansicht nach nicht die ganze Tabelle.

Zitat von: Bitsqueezer am September 20, 2024, 21:46:01Die 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.
Aus diesem Grund will ich sie ja auch nicht verwenden. Vielen Dank. Da waren auch für mich neue Sachen dabei.

Zitat von: Bitsqueezer am September 20, 2024, 21:46:01Es gibt auch andere Varianten, z.B. erst nach der Eingabe des 3. Zeichens die Suche zu starten.
Ja, dass ist möglich. Aber ich will schon ab dem 1. Zeichen mit der Suche beginnen und sehen, wie sich das auf die Ergebnisauswahl auswirkt.

Zitat von: Bitsqueezer am September 20, 2024, 21:46:01Ich 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.
Dann sehe ich aber die Änderung im Filter immer erst, wenn ich das komplette Wort eingeben habe. Wenn es für ein Wort keine Ergebenisse gibt, darf ich dann iterativ die Buchstabenfolge meiner Eingabe reduzieren, bis ich Ergebnisse erhalte. Das finde ich umständlich in der Benutzung und verlängert den Suchprozess. Dass der VBA-Code länger braucht um durchzulaufen ist eine andere Sache. Wenn noch nicht so viele Daten enthalten sind, merke ich das als Benutzer ja nicht.

Zitat von: Bitsqueezer am September 20, 2024, 21:46:01Meistens 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.
Danke für den Hinweis.
Beim nächsten Mal setze ich den Code ein, den ich auch im VBE eingearbeitet habe.

Zitat von: Bitsqueezer am September 20, 2024, 21:46:01Die 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.
Macht Sinn. Ich hatte diese Variante gewählt, weil ich mit Copy+Paste die Namen der Steuerelement in die "" eingefügt hatte und sich für mich durch den Codeaufbau einer klarer Pfad ergibt, welches Formular von welchem Unterformularsteuerelement jetzt angewählt ist. Die Fehlerquote erhöht sich natürlich.

Zitat von: Bitsqueezer am September 20, 2024, 21:46:01SQL-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.
Wieder was gelernt. Vielen Dank.

Zitat von: Bitsqueezer am September 20, 2024, 21:46:01Ganz nebenbei ist so ein SQL-Code in VBA dann auch schwierig zu debuggen.
Absolut. Nur manchmal brauchts ihn halt. Was ich gelernt habe, ist SQL schneller als VBA, weil es ja die interne Sprache von Access als Datenbank ist und ich damit auf Access's Kernkompetenz zurückgreife.

Zitat von: Bitsqueezer am September 20, 2024, 21:46:01Es ist daher besser, parametrisierte Abfragen zu verwenden oder Abfragen, die sich Vergleichswerte selbst aus dem Formular holen.
Das ist auf jeden Fall sicherer. Da bin ich auch gerade dran. Vielen Dank für den Tip.

KonradR

Hallo knobbi38,
Zitat von: knobbi38 am September 20, 2024, 23:19:43Um so etwas umzusetzen habe ich einfach mal die zu durchsuchenden Datenfelder komplett in ein Array geladen, per Quicksort sortiert und dann in eine Listbox geladen. Mit dem Change-Event wird dann per Binarysearch lokal in dieser Listbox gesucht und entsprechend positioniert, so daß man das Suchergebnis inklusive dem "Trefferumfeld" sehen kann. Wenn die Daten relativ wenig verändert werden, funktioniert das auch bei sehr "langsamen" Verbindungen selbst bei einer größeren Anzahl von DS ( > 30.000 ) sehr effizient.
Danke für den Tip. Damit werde ich mich mal beschäftigen.

Bitsqueezer

Hallo,

@Ulrich:
ZitatWenn man in einem Formular die AllowFilters-Eigenschaft auf FALSE setzt, kann ein Anwender nicht mehr einen per VBA gesetzten Filter manuell ändern oder löschen

Das geht natürlich, was allerdings auch die Usability eines Formulares einschränkt, da der User dann auch keine eigenen Filter verwenden kann. Hat man die RecordSource gesetzt, kann der User zusätzlich eigene Filter darauf verwenden. Alles eben eine Frage dessen, was man erreichen will.

ZitatWenn man die Recordsource ändert, müssen immer alle DS übertragen werden, erst dann kann lokal entschieden werden, welche DS relevant sind

Ja, im Fall eines Access-Backends stimmt das natürlich. Sorry dafür, ich denke halt bei Backend immer an SQL Server (bzw. DB-Server im Allgemeinen), weil ich grundsätzlich Access-Backends ablehne. :)
Zumindest besteht in diesem Fall kein Unterschied zwischen Filter und RecordSource, weil dann ja immer alle Datensätze geladen werden müssen.

@KonradR :
ZitatDu meinst, einen SQL-String in VBA zu erstellen und dann der Recordsource Eigenschaft des Steuerelements zuzuweisen?
Nein, es ging ja um die RecordSource des Formulares, zumindest nach Deinem Eingangspost. Aber das war damit gemeint, ja.

ZitatDas heißt, ich kann nur mit "Form_ApplyFilter" das manuelle Ändern des Filters durch den Nutzer unterbinden und sonst nicht?
Ja, oder mit AllowFilters, wie Ulrich angemerkt hat.

ZitatTablescan heißt ja, dass alle bzw. die meißten Daten einer Tabelle durchsucht werden. Es wird doch aber nur in einem Feld eines jeden Datensatzes gesucht. Das ist, meiner Ansicht nach nicht die ganze Tabelle.
Natürlich, es ist nur das betreffende Feld. Es ändert aber nichts daran, daß die gesamte Tabelle gelesen werden muß, das ist ein Tablescan. Bei der Suche in einem Index wird die Tabelle selbst nicht angerührt bzw. erst, wenn die gefundenen Datensätze geladen werden sollen. Das ist dann entweder ein Indexscan oder ein Indexseek.

Ich empfehle übrigens, auf "SELECT *" zu verzichten und grundsätzlich immer die Liste der wirklich benötigten Felder anzugeben, selbst wenn alle benötigt werden. Bei einer späteren Änderung der Tabelle werden dann keine unnötigen Daten übertragen. Ein Tool wie das kostenlose V-Tools mit Total Deep Search hilft sehr gut, Namen, die selbst die Auto-Namensanpassung nicht findet, zu finden und anzupassen.

ZitatDann sehe ich aber die Änderung im Filter immer erst, wenn ich das komplette Wort eingeben habe. Wenn es für ein Wort keine Ergebenisse gibt, darf ich dann iterativ die Buchstabenfolge meiner Eingabe reduzieren, bis ich Ergebnisse erhalte. Das finde ich umständlich in der Benutzung und verlängert den Suchprozess. Dass der VBA-Code länger braucht um durchzulaufen ist eine andere Sache. Wenn noch nicht so viele Daten enthalten sind, merke ich das als Benutzer ja nicht.

Bei solchen Dingen würde ich Usability bei den Großen abschauen. Google oder andere Suchmaschinen etwa haben mit irrsinig großen Datenbeständen zu tun. Du bekommst während der Eingabe trotzdem keine Suchergebnisse angezeigt, stattdessen erhältst Du zum einen Vorschläge aus eigenen vergangenen Suchen (z.T. natürlich auch vom Browser), zum anderen die häufigsten Suchen anderer Besucher, in denen Deine Suchwörter vorkommen.
Was spricht dagegen, es ebenso zu machen? Die Anzahl Datensätze in einer "vergangene Suchen"-Tabelle wird eher gering sein. Da kann man dann mit Change-EVent leben. Keine Suchmaschine käme klar, wenn etliche User mit jedem eingegebenen Zeichen sofort alle Ergebnisse aus dem Internet gelistet bekämen.

Du könntest Dir auch meine "BestMatchV3"-Demodatenbank anschauen, bei der in komplexen Texten gesucht werden kann, indem man einfach frei Wörter eingibt. Dabei werden dann Punkte vergeben, wie oft welches Wort in welchem Ergebnis gefunden wurde und von wievielen der eingegebenen Wörter. Damit kann man dann sehr schnell das gewünschte wiederfinden, schon daher, weil man eben mehr als ein Wort eingeben kann.
Findest Du auf meiner Downloadseite unter www.ccedv.de .

ZitatAbsolut. Nur manchmal brauchts ihn halt. Was ich gelernt habe, ist SQL schneller als VBA, weil es ja die interne Sprache von Access als Datenbank ist und ich damit auf Access's Kernkompetenz zurückgreife.

Definitiv, man sollte SQL immer VBA vorziehen, wo immer es machbar ist - keine Frage!
Falsch ist dagegen zu glauben, daß man dazu SQL-Strings in VBA einbauen müßte. In den meisten Fällen kann man auf eine gespeicherte Abfrage zurückgreifen. Und wenn man dynamische Parameter braucht, dann klickt man im Abfragedesigner einfach mal auf "Parameter" in der Ribbon-Leiste und erstellt (dazu auch noch) Parameter, die Datentypen haben.
Deren Namen kann man dann einfach in der Abfrage (mit eckigen Klammern) einsetzen.
In VBA ruft man die Abfrage dann aus der Liste der QueryDefs als QueryDef-Objekt auf und dieses Objekt enthält eine "Parameters"-Collection, die je Parameter mit dem entsprechenden Namen angesprochen werden kann. Deren Wert kann man in VBA dann befüllen, was einer SQL Injection vorbeugt, da man hier den SQL-Text nicht verändert.

Natürlich gibt es auch Situationen, in denen man den SQL-Text anpassen muß, was sich "dynamisches SQL" nennt, hier muß man dann aber eben bestmöglichst verhindern, daß es zu Problemen kommt.

Gruß

Christian

KonradR

Zitat von: Bitsqueezer am September 22, 2024, 20:56:37Keine Suchmaschine käme klar, wenn etliche User mit jedem eingegebenen Zeichen sofort alle Ergebnisse aus dem Internet gelistet bekämen.
Absolut. Meine Datenbank ist ja so klein, da ist das eher keine Problem. Wenn dass dann größer wird, kann ich ja immer noch über eine Änderung nachdenken.

Zitat von: Bitsqueezer am September 22, 2024, 20:56:37Findest Du auf meiner Downloadseite unter www.ccedv.de .
Zitat von: Bitsqueezer am September 22, 2024, 20:56:37Du könntest Dir auch meine "BestMatchV3"-Demodatenbank anschauen, bei der in komplexen Texten gesucht werden kann, indem man einfach frei Wörter eingibt.
Danke für den Tip. Wow, extrem umfangreich. Wie lange hast du schon mit Access zu tun?

Zitat von: Bitsqueezer am September 22, 2024, 20:56:37In VBA ruft man die Abfrage dann aus der Liste der QueryDefs als QueryDef-Objekt auf und dieses Objekt enthält eine "Parameters"-Collection, die je Parameter mit dem entsprechenden Namen angesprochen werden kann. Deren Wert kann man in VBA dann befüllen, was einer SQL Injection vorbeugt, da man hier den SQL-Text nicht verändert.

Natürlich gibt es auch Situationen, in denen man den SQL-Text anpassen muß, was sich "dynamisches SQL" nenn
Danke dafür. Damit werde ich mich mal näher befassen. Ein sehr umfangreiches Thema.

Bitsqueezer

Hallo,

ZitatWie lange hast du schon mit Access zu tun?
Seit es Access gibt... :)

Und mit Datenbanken noch länger.

Gruß

Christian