Mai 17, 2021, 11:10:57

Neuigkeiten:

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


Filter bei nicht angezeigten Feldern?!

Begonnen von Xoar, Mai 01, 2021, 15:44:53

⏪ vorheriges - nächstes ⏩

Xoar

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?! 🤔 

DF6GL

Mai 01, 2021, 16:53:51 #1 Letzte Bearbeitung: Mai 01, 2021, 17:36:36 von DF6GL
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.



Josef P.

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

Xoar

@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

Josef P.

Mai 01, 2021, 20:25:44 #4 Letzte Bearbeitung: Mai 01, 2021, 20:36:37 von Josef P.
Hallo!

Falls es eine meiner Filter-Klassen ist, gibt es eine extra Methode für die In- oder Exists-Bedingung.

Beispiel für FilterStringBuilder-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

Xoar

Ich teste es gleich morgen mal.

Vielen Dank 👍🏻

DF6GL

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.



Xoar

@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

Josef P.

Mai 02, 2021, 14:08:20 #8 Letzte Bearbeitung: Mai 02, 2021, 14:32:52 von Josef P.
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

Xoar

Ok, vielen Dank für die Hilfe.

Dann kann ich meine Version 2.0 nun so umsetzen wie erhofft.