Hallo Profis,
ich habe mir ja ein schönes Formular gebaut, wo ich über Steuerelemente ein Formular dynamisch filtere. Klappt auch alles super, aber leider nicht ausreichend.
Mein Problem für Variante 2.0
Ich habe eine Abfrage mit einigen Stammdaten erzeugt (MitarbeiterID, Vorname, Nachname, Alter...) diese Abfrage hat jedoch auch viele 1:N Beziehungen zu anderen Tabellen (z.B Führerscheine, Qualifikationen, Untersuchungen...)
Diese Felder kann ich der Abfrage aber nicht sichtbar hinzufügen (im Abfragegenerator der Haken bei sichtbar) sonst klappt die Gruppierung nach MitarbeiterID nicht. Der Mitarbeiter ist ja sonst je nach Qualifikation etc mehrfach angezeigt.
Wenn ich jetzt ein solches Feld fix als Bedingung definiere und ein Kriterium zuweise, klappt das ja, aber wenn dieses Feld kein Kriterium hat und als ,,nicht anzeigen" markiert ist, löscht Access das aus der Abfrage. Wird ja nicht benötigt....
Wenn ich dann aber in meinem Formular für ein solches Feld einen Filter setzte, klappt das ja nicht, da dieses Feld nicht in der Abfrage vorkommt....
Wie kann ich dieses Problem lösen?
Ziel soll es sein, ein Formular mit vielen Filtersteuerelementen zu haben, die sich AUCH auf verknüpfte 1:N Tabellen beziehen. Das Abfrageergebnis soll als Datenblattansicht in einem Formular angezeigt werden, aber nur mit den o.g. Stammdatenfeldern.
Muss ich meine Filterklasse ändern/aufgeben und dem Formular einen
passenden SQL String als Datensatzherkunft angeben?
Oder übersehe ich da was?! 🤔
Hallo,
ZitatMuss ich meine Filterklasse ändern/aufgeben
kann ich nicht sagen. Vermutlich musst Du sie ändern...
Zitateinen passenden SQL String als Datensatzherkunft angeben
Ja..
Eine (von mehreren) Möglichkeit(en):
(Wenn nur Felder aus der Haupttabelle angezeigt werden und nicht editierbar sein sollen.)
Erstell eine gruppierende Abfrage ("qry_StammdatenFilter") über die Haupttabelle mit den benötigten Feldern und allen nötigen N-Tabellen sowie einer Bedingungsspalte
Feld: 1
Kriterium: 1
(mit dem Abfragegenerator wird dann in der SQL-Ansicht
Where ((1)=1) erzeugt.
In den Ereignisprozeduren für die Filtervorgänge wird das Dummy-Kriterium durch den per VBA generierten aktuellen Condition-String (mit Replace) ersetzt und der Datenherkunft des Forms zugewiesen:
'(roher Luftcode!)
Sub btnFilter_Click()
Dim _
strSQL as String, _
strKrit as String
If Not IsNull (Me!Qual_Bezeichnung) Then strKrit = strKrit & " And Qual_Bezeichnung Like '" & Me!Qual_Bezeichnung & "*'"
If Not IsNull (Me!Untersuchung_Bez) Then strKrit = strKrit & " And Untersuchung_Bez Like '" & Me!Untersuchung_Bez & "*'"
.
.
.
.
strSQL = Currentdb.Querydefs!qry_StammdatenFilter.SQL
If Len(strKrit) > 1 Then
strKrit = Mid(strKrit,6)
strSQL = Replace(strSQL,"((1)=1)", strKrit)
End if
Me.Recordsource = strSQL
End Sub
Wenn die Haupttabellendaten editierbar sein sollen, muss der o. generierte SQL-String zusätzlich mit der Stammdatentabelle über die StammdatenID mit Inner Join verknüpft werden.
Hallo!
Falls ich dich richtig verstehe, willst du Datensätze anzeigen, die in der 1:n-Tabelle einen Treffer auf einen eingebenen Filter enthalten.
Dafür könntest du in deiner Filterklasse einen Bedingung mit Exisits oder PK in(select FK from .. where ...) erzeugen.
mfg
Josef
@franz Alles klar, habe ich verstanden.
Bei mehreren N Tabellen müsste ich dann auch mehrere Dummy-Bedingungen definieren. Wird eine Bedingung 1=1 unbehandelt gelassen, also wie ein Platzhalter?
@Josef P. ich glaube dass es sich sogar um deine Filterklasse handelt. Zumindest taucht dein Nickname im Code auf. (Hab ich über die Beiträge von Andre Minhorst).
Ich verstehe das so, dass ich dann über
.addcriteria(,,PK in(SELECT FK FROM tblNBeziehung WHERE Bedingungsfeld = Bedingung")
im Hauptformular alle Datensätze herausfiltere, die nicht durch den Code oben zurück gegeben werden?!
Grüße
Hallo!
Falls es eine meiner Filter-Klassen ist, gibt es eine extra Methode für die In- oder Exists-Bedingung.
Beispiel für FilterStringBuilder (https://source.access-codelib.net/filedetails.php?repname=CodeLib+%28Entwurf%2C+branches%2Fdraft%29&path=%2Fdata%2FFilterStringBuilder.cls)-Klasse:
With New FilterStringBuilder
...
With .AddSubSelectCriteria("PK", SQL_In, "Select FK from SubTabelle", True)
' das True am Ende nimmt die In-Bedingung nicht auf, falls in DeinFilterControl kein Filterwert gesetzt ist.
.Add "FeldInSub", SQL_Numeric, SQL_Equal, Me.DeinFilterControl.Value
End With
FilterParameter = .ToString()
End With
mfg
Josef
Ich teste es gleich morgen mal.
Vielen Dank 👍🏻
Hallo,
ZitatBei mehreren N Tabellen müsste ich dann auch mehrere Dummy-Bedingungen definieren. Wird eine Bedingung 1=1 unbehandelt gelassen, also wie ein Platzhalter?
Eher nein. Das Kriterium ( ist nicht nur "Platzhalter", sondern ein funktionierendes Kriterium)
1=1 befindet sich in der Abfrage, die über mehrere Tabellen verknüpft.
Wird das Kriterium nicht geändert (ersetzt) , ist die Where-Condition "True" und alle DS werden geliefert.
Zitatauch mehrere Dummy-Bedingungen definieren
So kann man nicht sagen. Du definierst (per Code) ein zusammengesetztes Kriterium (strKrit), das sich auf ein oder mehrere Felder in den verwendeten Tabellen bezieht und den "Platzhalter"
(1)=1 ersetzt.
@franz alles klar, dann habe ich das auch verstanden :)
@Josef P. hatte wohl noch eine alte Filterklasse implementiert, da gab es die Methoden noch garnicht.
Jetzt nach dem Import der neuen Klasse, stehen diese zur Verfügung.
With .AddSubSelectCriteria("MitarbeiterID", SQL_In, "SELECT F_MitarbeiterID FROM tblQualiMitarbeiter", True)
.AddCriteria ("[Seitwann] is not null")
.Add "F_QualiID", SQL_Numeric, SQL_Equal, Me.filQuali1.Value
End With
damit klappt es, freut mich :)
Eine Frage habe ich noch, neben den Qualifikationen habe ich drei Buttons (AND, OR, NOT), heißt wenn ich eine zweite Qualifikation auswähle, sollen diese beiden mit einen der Parameter verknüpft werden.
Dazu nutze ich dann die newConditionGroup mit dem jeweiligen Parameter, oder?
Grüße
Hallo!
Vorab: Jetzt wird es sehr FilterStringBuilder-lastig. Kannst auch gerne per Mail an mich weitermachen, falls das hier im Forum nicht mehr rein passt.
Meinst du das mit der 2. Quali so:
With .AddSubSelectCriteria("MitarbeiterID", SQL_In, "SELECT F_MitarbeiterID FROM tblQualiMitarbeiter", True)
.AddCriteria ("[Seitwann] is not null")
With .NewConditionGroup(SQL_And) ' hier AND bzw. OR
.Add "F_QualiID", SQL_Numeric, SQL_Equal, Me.filQuali1.Value
.Add "F_QualiID", SQL_Numeric, SQL_Equal, Me.filQuali2.Value
End With
End With... das würde einen SQL-Ausdruck erzeugen, der kein Ergebnis liefert.
F_QualiID kann nicht 123 und im gleichen Datensatz 456 sein.
Quali1 oder Quali2 würde so aussehen:
With .AddSubSelectCriteria("MitarbeiterID", SQL_In, "SELECT F_MitarbeiterID FROM tblQualiMitarbeiter", True)
.AddCriteria ("[Seitwann] is not null")
.Add "F_QualiID", SQL_Numeric, SQL_In, Array(Me.filQuali1.Value, Me.filQuali2.Value)
End With
Wobei ich das AddCriteria anders einbauen würde, damit das subselect nicht greift, falls nicht nach Quali gefiltert wird. (Siehe später beim Beispiel mit den 2 Subselects.)
Quali1 und Quali2 könnte so aussehen (funktioniert aber nur, wenn beide befüllt sind:
With .AddSubSelectCriteria("MitarbeiterID", SQL_In, "SELECT F_MitarbeiterID FROM tblQualiMitarbeiter [WhereStatement] and [Seitwann] is not null group by F_MitarbeiterID having count(*) = 2", True, True)
.Add "F_QualiID", SQL_Numeric, SQL_In, Array(Me.filQuali1.Value, Me.filQuali2.Value)
End With
Quali1 und/oder Quali2 könntest du auch mit 2 In-Statements erzeugen und and/or über NewConditionGroup einstellen:
With .NewConditionGroup(SQL_Or) ' oder SQL_And ... je nach Auswahl
With .AddSubSelectCriteria("MitarbeiterID", SQL_In, "SELECT F_MitarbeiterID FROM tblQualiMitarbeiter [WhereStatement] and [Seitwann] is not null", True, True)
.Add "F_QualiID", SQL_Numeric, SQL_In, Me.filQuali1.Value
End With
With .AddSubSelectCriteria("MitarbeiterID", SQL_In, "SELECT F_MitarbeiterID FROM tblQualiMitarbeiter [WhereStatement] and [Seitwann] is not null", True, True)
.Add "F_QualiID", SQL_Numeric, SQL_In, Me.filQuali2.Value
End With
End With
Die letzte Variante erzeugt 2 Subselects ... das kann laufzeittechnisch lästig werden.
mfg
Josef
Ok, vielen Dank für die Hilfe.
Dann kann ich meine Version 2.0 nun so umsetzen wie erhofft.