Access-o-Mania

Access-Forum (Deutsch/German) => Formular => Thema gestartet von: ellinho am April 27, 2015, 17:37:29

Titel: etwas kompliziertere (?) Filterfunktion
Beitrag von: ellinho am April 27, 2015, 17:37:29
Hallo zusammen.
Ich möchte in einem Formular, das zum Überprüfen/Editieren von vorhandenen Datensätzen dient, eine Filterfunktion einbauen. Die Tabelle, die zugrunde liegt, enthält die Namen der Mitarbeiter (Vorname, Nachname, Personalnummer) und Abwesenheitszeiträume (Datumvon und Datumbis). Nun würde ich gerne über ein Drop-Down-Menü den Mitarbeiter auswählen und daraufhin einen Zeitraum eingrenzen. Es wäre theoretisch brauchbar, wenn man "Monat" und "Jahr" über Dropdown-Menüs auswählen kann. Beim Klick auf "Suchen" sollten dann sämtliche Datensätze ausgegeben werden, die den ausgewählten Mitarbeiter betreffen und in den ausgewählten Zeitraum fallen. Z.B. wähle ich Mitarbeiter Schmidt aus und habe eine Abwesenheitszeit vom 28.03.2015 bis 03.04.2015 sollte dieser Datensatz sowohl bei der Auswahl von März 2015 als auch bei der Auswahl von April 2015 ausgegeben werden, weil der Abwesenheitszeitraum in beide Monate fällt. Ich hoffe, es ist klar geworden, was umgesetzt werden soll und habt eine Idee, wie sich das realisieren lässt.
Titel: Re: etwas kompliziertere (?) Filterfunktion
Beitrag von: el_gomero am April 27, 2015, 19:33:24
Hallo,

Zitat
Nun würde ich gerne über ein Drop-Down-Menü den Mitarbeiter auswählen und daraufhin einen Zeitraum eingrenzen. Es wäre theoretisch brauchbar, wenn man "Monat" und "Jahr" über Dropdown-Menüs auswählen kann.

Du brauchst also mindestens 3 Kombifelder. Das erste beinhaltet die Personendaten, das 2. Monat und Jahr für die Eingrenzung des Zeitraums von und das 3. Monat und Jahr für bis. Als Datenherkunft für die Monat / Jahr Kombis bietet sich eine Hilfstabelle an, die jeweils zB den 1. des Monats ausgibt. Die Anzeige wird mit Hilfe Format in ein taugliches Anzeigeformat ausgegeben.
Titel: Re: etwas kompliziertere (?) Filterfunktion
Beitrag von: ellinho am April 27, 2015, 19:47:06
Hallo Jürgen.

Danke erstmal für Deine Antwort.
Habe ich das richtig verstanden? Monat und Jahr in jeweils einem Kombifeld? Muss man das nicht immer getrennt auswählen? Für "Deine" Variante hätte ich jetzt mit insgesamt 5 Kombifeldern gerechnet. Hast Du vielleicht auch einen Tipp, wie ich es dann in VBA mit den Befehlen mache?
Bisher war es nur ein ungebundenes Textfeld, dass nach den Nachnamen gefiltert hat.

Private Sub Befehl25_Click()
Me.Filter = "Nachname Like '" & Me!Suchfeld_Nachname & "'"
  Me.FilterOn = True
End Sub

Nun wird es ja doch um einiges komplizierter.
Habe da aktuell allerdings noch keine Idee.
Kannst Du mir da vielleicht ein bißchen auf die Sprünge helfen?
Titel: Re: etwas kompliziertere (?) Filterfunktion
Beitrag von: el_gomero am April 27, 2015, 20:22:37
ich denke es wird einfacher, nicht komplizierter. Die Suche nach der Person solltest du aber über die ID lösen. Auch wenn es bei dir (noch) nicht der Fall ist, es kann Personen geben, die den gleichen Vor- und Nachnamen haben. Die Auswahl kann ruhig über die Namen erfolgen, allerdings sollte bei Namensgleichheit ein weiteres Kriterium zur eindeutigen Identifikation zur Verfügung stehen.

Was hast du denn bisher?
Titel: Re: etwas kompliziertere (?) Filterfunktion
Beitrag von: ellinho am April 27, 2015, 20:27:50
Bisher habe ich nur das, was ich geschrieben habe.
Muss jetzt erst das Textsuchfeld für die Person in ein Kombifeld umwandeln und die Kombifelder mit Monat/Jahr einbauen. Dann geht es ans "Eingemachte". ;)
Titel: Re: etwas kompliziertere (?) Filterfunktion
Beitrag von: el_gomero am April 27, 2015, 20:30:35
gut, wenn's beim Einmachen klemmt, melden  ;D
Titel: Re: etwas kompliziertere (?) Filterfunktion
Beitrag von: ellinho am April 27, 2015, 22:25:05
Vielen Dank.
Ich werde es mal probieren.
Titel: Re: etwas kompliziertere (?) Filterfunktion
Beitrag von: ellinho am Mai 06, 2015, 13:07:18
Ich bin jetzt an folgendem Punkt:
Habe ein Unterformular mit zum Testen mal 4 Textfeldern erstellt und folgenden Code hinterlegt:
Private Sub Form_Load()
RecordSource = "SELECT * FROM Abwesenheit ORDER BY Datumvon"
Text1.ControlSource = "Personalnummer"
Text2.ControlSource = "Datumvon"
Text3.ControlSource = "Datumbis"
Text4.ControlSource = "Abwesenheitsgrund"
End Sub

Somit werden mir im Unterformular schon mal alle Datensätze angezeigt. Nun möchte ich über das Hauptformular die Ausgabe des Unterformulars filtern können. Am liebsten über Kombifelder. Nach Auswahl von Name und Auswahl von Monat und Jahr sollten nach Klick auf eine Schaltfläche "Suchen" alle Datensätze im Unterformular ausgegeben werden, die den Namen betreffen und in den Auswahlzeitraum fallen.(entweder das Datumvon oder das Datumbis). Wenn ich also Mitarbeiter "Schmidt" und "März 2015" auswähle, sollten ein Abwesenheitszeitraum vom 28.02.2015 bis 03.03.2015 genauso angezeigt werden wie ein Abwesenheitszeitraum vom 28.03.2015 bis 04.04.2015. Das Hauptformular bezieht die Daten aus einer Abfrage und holt sich folgende Daten: "Personalnummer", "Vorname", "Nachname", "Datumvon", "Datumbis" und "Abwesenheitsgrund".

In den Ergebnissen im Unterformular sollten dann den ausgewählten Mitarbeiter und Zeitraum betreffenden Abwesenheitszeiten mitsamt des Abwesenheitsgrunds ausgegeben werden.
Was muss ich für einen Code für die Schaltfläche "Suchen" hinterlegen und wie muss ich noch ggfs. den Code für Haupt- bzw. Unterformular anpassen?
Titel: Re: etwas kompliziertere (?) Filterfunktion
Beitrag von: MaggieMay am Mai 08, 2015, 01:11:21
Hallo,

ZitatWenn ich also Mitarbeiter "Schmidt" und "März 2015" auswähle
wenn du das Kombifeld zur Auswahl des Zeitraums um die Spalten "von" und "bis" erweiterst, also bei "Januar 2015" mit den Angaben "1.1.2015" und "31.1.2015", so kannst du die Spalten zum Filtern einsetzen.

Zitatund wie muss ich noch ggfs. den Code für Haupt- bzw. Unterformular anpassen?
An welchen Code denkst du da?
Titel: Re: etwas kompliziertere (?) Filterfunktion
Beitrag von: ellinho am Mai 12, 2015, 10:35:36
@MaggieMay
Sorry. Kam ein paar Tage nicht dazu, mich weiter damit zu beschäftigen.
Das ist eine gute Idee mit dem Hinzufügen der Spalten im Kombi bei Auswahl des Monats. Danke dafür. :)
An welchen Code hatte ich gedacht? Ich habe ja im UFO bereits testweise einen Code eingesetzt, mit dem momentan alle Datensätze im UFO angezeigt werden. Muss da nicht auch weiterhin ein Code drin stehen, damit gefilterte Datensätze im Hauptformular in bestimmten Feldern des UFOs angezeigt werden? Habe da einfach nur noch ein Verständnisproblem.  ;)
Titel: Re: etwas kompliziertere (?) Filterfunktion
Beitrag von: MaggieMay am Mai 12, 2015, 17:26:37
Hi,

den Code im Unterformular halte ich für absolut überflüssig. Binde das Unterformular an die Tabelle oder Abfrage und die Textfelder an die Datenfelder. Das dynamische Einstellen von RecordSource und ControlSource wird doch gar nicht benötigt.

Ein Button im Hauptformular könnte dann mit folgendem Code bestückt werden:
Private Sub btn_Filtern_Click()
    Dim strFilter As String
    If [color=blue]IsNull([/color]Me!cboMitarbeiter) Or IsNull(Me!cboMonat) Then
        MsgBox "Bitte erst Person und Monat auswählen!"
    Else
        strFilter = "Personalnummer=" & Me!cboMitarbeiter & " And " & CLng(DateValue(Me!cboMonat.Column(1))) & " Between DatumVon And DatumBis"
        Me!ufControlName.Form.Filter = strFilter
        Me!ufControlName.Form.FilterOn = True
    End If
End Sub


{Edit: Fehlerkorrektur}
Titel: Re: etwas kompliziertere (?) Filterfunktion
Beitrag von: ellinho am Mai 13, 2015, 13:59:28
Vielen Dank für Deinen Tipp.
Ich habe es mal etwas modifiziert und nun sieht es folgendermaßen aus:

Private Sub btn_Filtern_Click()
    Dim strFilter As String
    If IsNull(Me!cbo_Mitarbeiter) Or IsNull(Me!cbo_Monat) Then
        MsgBox "Bitte erst Zeitraum auswählen!"
    Else
        strFilter = "Personalnummer=" & Me!cbo_Mitarbeiter.Column(2) & " And " & CLng(DateValue(Me!cbo_Monat.Column(1))) & " Between DatumVon And DatumBis  OR Personalnummer=" & Me!cbo_Mitarbeiter.Column(2) & " And " & CLng(DateValue(Me!cbo_Monat.Column(2))) & " Between Datumvon And DatumBis"
        Me!AbwesenheitloeUF.Form.Filter = strFilter
        Me!AbwesenheitloeUF.Form.FilterOn = True
        End If
    End Sub


Das funktioniert auch soweit klasse. Vielen Dank schon mal.
Mein aktuelles Problem liegt lediglich noch darin, dass bei Öffnen des Formulars sämtliche Datensätze im Unterformular angezeigt werden (am schönsten wäre eigentlich, das UFO würde erst nach Auswahl von Mitarbeiter und Zeitraum überhaupt sichtbar) und der Nachname des ersten Mitarbeiters (Personalnummer 000001) bereits im Dropdown cbo_Mitarbeiter ausgewählt ist. Wähle ich daraufhin einen anderen Mitarbeiter im cbo_Mitarbeiter aus, wird der Nachname der Personalnummer 000001 mit dem Nachnamen des ausgewählten Mitarbeiters überschrieben. (direkt in den Stammdaten in der Tabelle Mitarbeiter)  :(
Idealerweise sollten beide Kombis beim Öffnen des Formulars zunächst leer sein. Bekomme ich nur irgendwie nicht hin. Wahrscheinleich habe ich ein Brett vor dem Kopf.  :-\
Vielleicht hat jemand noch einen kleinen Tipp, der mich wieder auf den richtigen Weg bringt.  8)

Titel: Re: etwas kompliziertere (?) Filterfunktion
Beitrag von: MaggieMay am Mai 13, 2015, 16:42:50
Hi,

das sieht ganz danach aus, als wären die Kombifelder gebunden, das dürfen sie natürlich nicht sein.
Zum Suchen setzt man ungebundene Kombi- oder auch Textfelder ein.

Und was das Unterformular betrifft, das kannst du ja standardmäßig ausblenden und erst beim Filtern über die Visible-Eigenschaft des Steuerelements einblenden.
Titel: Re: etwas kompliziertere (?) Filterfunktion
Beitrag von: ellinho am Mai 13, 2015, 18:08:24
Vielen Dank für Deine Hilfe.
Ein Kombi war wirklich gebunden. Nun funktioniert es fast einwandfrei.
Momentan "fange" ich allerdings noch nicht alle Datensätze...das liegt wohl an der Between-Funktion. Wenn ein Zeitraum z.B. vom 11.05.2015 bis 15.05.2015 in der zu filternden Tabelle/Abfrage steht, bekomme ich den nicht angezeigt, weil in der Zeile des Kombifelds in Spalte 1 ja der 01.05.2015 und in Spalte 2 der 31.05.2015 stehen. Diese beiden liegen ja nicht zwischen dem 11.05.2015 und 15.05.2015. Habe schon an die Funktion DatePart gedacht...weiß nur noch nicht, wie ich die Syntax aufbauen soll. Hast Du dazu noch eine Idee?

P.S.: Das mit den z.T. fehlenden Datensätzen ist mir gerade eben beim Testen erst aufgefallen... :-\
Titel: Re: etwas kompliziertere (?) Filterfunktion
Beitrag von: MaggieMay am Mai 13, 2015, 18:25:29
Hallo,
ZitatDiese beiden liegen ja nicht zwischen dem 11.05.2015 und 15.05.2015.
umgekehrt passt's schon eher.

Das mit der Datumsüberprüfung ist ein wenig komplexer, du musst von und bis einzeln prüfen ob es Überschneidungen mit dem Auswahlzeitraum gibt.
Titel: Re: etwas kompliziertere (?) Filterfunktion
Beitrag von: ellinho am Mai 13, 2015, 20:12:15
Hallo.

Ja. Ich denke auch. Der Aufbau macht mir bezüglich der Syntax nur zu schaffen.
Titel: Re: etwas kompliziertere (?) Filterfunktion
Beitrag von: MaggieMay am Mai 13, 2015, 21:21:02
Ich habe hier mal eine Vorlage für dich:
Dim lngVon As Long, lngBis As Long     
lngVon = CLng(DateValue(Me!cbo_Monat.Column(1)))   
lngBis = CLng(DateValue(Me!cbo_Monat.Column(2)))
strFilter = "Personalnummer=" & Me!cbo_Mitarbeiter & " And " & _
                "(DatumVon < " & lngVon & " And DatumBis > " & lngBis & ") OR " & _
                "(DatumVon >=" & lngVon & " And DatumBis <=" & lngBis & ") OR " & _
                "(DatumVon <=" & lngBis & " AND DatumBis >=" & lngBis & ")"


wobei vorausgesetzt wird, dass im Kombi-Mitarbeiter die ID (wieder) an erster Stelle steht und die gebundene Spalte ist. Die Sichtbarkeit der Spalten wird über die Spaltenbreiten geregelt.

Du kannst dir die verschiedenen Möglichkeiten mit Hilfe eines Zeitstrahls recht gut veranschaulichen.
|-----------------------------------------------------------|     Monats-umschließender Zeitbereich
|----------|           |------------|             |--------------|     weitere Möglichkeiten
      |------------------ Monat X ---------------------|           Vergleichszeitraum
Titel: Re: etwas kompliziertere (?) Filterfunktion
Beitrag von: ellinho am Mai 14, 2015, 00:45:14
Hallo.
Danke schon mal vorab für Deine Hilfe.
Ich werde es morgen mal in Ruhe ausprobieren. Es sieht vom Code her aber auf jeden Fall schon mal so aus, als könnte es so klappen.  :D
Vielen Dank !!!

Viele Grüße
ellinho
Titel: Re: etwas kompliziertere (?) Filterfunktion
Beitrag von: Josef P. am Mai 14, 2015, 11:12:52
Hallo!

Falls es darum geht, sich überschneidende Bereiche zu finden, sollte auch folgendes funktionieren:

Prinzip:
StartDatum <= DatumBis AND EndeDatum >= DatumVon

Grundsätzlicher Tipp zum Konvertieren eines Datumswertes in SQL-Text.
Verzichtet auf die CLng-Konvertierung. Wenn man einmal auf ein DBMS mit ODBC-verknüpften Tabellen umsteigt, kann das falsche Werte liefer, da z. B. 0 ein im Jet-System ein anderes Datum als in MSSQL-DBMS darstellt.
Datum als richtiges Datum (mit #-Eingrenzung) formatiert wird dagegen immer richtige über ODBC an das jeweilige DBMS weitergegeben.

Natürlich kann man die CLng-Konvertierung lassen, wenn man ausschließlich Jet verwendet. Ich halte es nur für keinen besonderen Aufwand, gleich in einen kompatiblen Text zu formatieren - vor allem, da man solche Konvertierungen in ein paar Hilfsfunktionen unterbringen kann.

Beispiel-Code:
strFilter = "Personalnummer=" & SqlTools.NumberToSqlText(Me!cbo_Mitarbeiter) & " And " & _
            "DatumVon <= " & SqlTools.DateToSqlText(datEnde)) & " And " & _
            "DatumBis >=" & SqlTools.DateToSqlText(datStart)


mfg
Josef
Titel: Re: etwas kompliziertere (?) Filterfunktion
Beitrag von: ellinho am Mai 14, 2015, 21:44:33
Hallo.
Habe das
ZitatDim lngVon As Long, lngBis As Long     
lngVon = CLng(DateValue(Me!cbo_Monat.Column(1)))   
lngBis = CLng(DateValue(Me!cbo_Monat.Column(2)))
strFilter = "Personalnummer=" & Me!cbo_Mitarbeiter & " And " & _
                "(DatumVon < " & lngVon & " And DatumBis > " & lngBis & ") OR " & _
                "(DatumVon >=" & lngVon & " And DatumBis <=" & lngBis & ") OR " & _
                "(DatumVon <=" & lngBis & " AND DatumBis >=" & lngBis & ")"
mal ausprobiert. Vielen Dank erst mal für die Idee.
Leider "fange" ich damit noch nicht alle Datensätze. Wenn ein monatsübergreifender Zeitraum vorliegt, soll der selbe Datensatz bei Auswahl des einen sowie des anderen Monats angezeigt werden.

Ich habe es auch mal mit Datepart probiert. Allerdings war Deine Funktion da schon weiter, denn bei Datepart wird mir überhaupt nichts angezeigt. Mit der Datepart-Funktion käme ich mit einer Datumsspalte im Auswahlkombi aus. Hier mal mein Code :
ZitatDim KombiMon As Variant, KombiJahr As Variant, DatumvonMon As Variant, DatumvonJahr As Variant, DatumbisMon As Variant, DatumbisJahr As Variant
KombiMon = DatePart("m", Me!cbo_Monat.Column(1))
KombiJahr = DatePart("yyyy", Me!cbo_Monat.Column(1))
DatumvonMon = DatePart("m", Datumvon)
DatumvonJahr = DatePart("yyyy", Datumvon)
DatumbisMon = DatePart("m", Datumbis)
DatumbisJahr = DatePart("yyyy", Datumbis)

    strFilter = "Personalnummer=" & Me!cbo_Mitarbeiter.Column(0) & " And " & DatumvonMon & " = " & KombiMon & " AND " & DatumvonJahr & " = " & KombiJahr & " OR Personalnummer=" & Me!cbo_Mitarbeiter.Column(0) & " And " & DatumbisMon & " = " & KombiMon & " AND " & DatumbisJahr & " = " & KombiJahr
So bekomme ich nur leider gar keinen Datensatz angezeigt. Gibt es noch eine andere Datumsfunktion, die man nehmen könnte?
Viele Grüße
ellinho
Titel: Re: etwas kompliziertere (?) Filterfunktion
Beitrag von: MaggieMay am Mai 14, 2015, 22:25:25
Hi,
ZitatLeider "fange" ich damit noch nicht alle Datensätze.
kann ich mir nicht vorstellen, alle möglichen Varianten werden doch damit abgedeckt.

Aber hast du auch den Vorschlag von Josef schon ausprobiert, der ist ja noch viel einfacher.
Titel: Re: etwas kompliziertere (?) Filterfunktion
Beitrag von: ellinho am Mai 14, 2015, 23:43:07
Hi.
Hab den "Fehler" gefunden :
ZitatDim lngVon As Long, lngBis As Long     
lngVon = CLng(DateValue(Me!cbo_Monat.Column(1)))   
lngBis = CLng(DateValue(Me!cbo_Monat.Column(2)))
strFilter = "Personalnummer=" & Me!cbo_Mitarbeiter & " And " & _
                "(DatumVon < " & lngVon & " And DatumBis > " & lngBis & ") OR " & _
                "(DatumVon >=" & lngVon & " And DatumBis <=" & lngBis & ") OR " & _
                "(DatumVon <=" & lngBis & " AND DatumBis >=" & lngBis & ")"
Statt der letzten Variable "IngBis" musste ich "IngVon" einsetzen. Damit werden nun alle Datensätze wie gewünscht gefiltert. Vielen vielen Dank nochmal ! :)
Titel: Re: etwas kompliziertere (?) Filterfunktion
Beitrag von: Josef P. am Mai 15, 2015, 11:01:06
Hallo!

Wenn du mit der gezeigten SQL-Bedingung alle Datensätze erhältst, ist das ein wenig Zufall. ;-)

Beispiel:
lngVon = Clng(#2/1/2015#) '01.02.2015
lngBis = Clng(#2/28/2015#) '28.02.2015
Anm.: die CLng-Konvertierung lasse ich so wie sie ist, auch wenn ich das persönlich als "unsauber" betrachte.

DatumVon = 01.01.2015
DatumBis = 05.02.2015
=>
DatumVon < lngVon .. OK
DatumBis > lngBis .. Falsch

DatumVon >= lngVon .. Falsch
DatumBis <= lngBis .. OK

DatumVon <= lngBis .. OK
DatumBis >= lngBis .. Falsch

Wenn du die gezeigte Or-Variante überprüfen lassen willst, musst du im Prinzip folgende Fälle berücksichtigen:
1. Von liegt vor dem Start des Vergleichszeitraums + Bis liegt nach dem Start
2. Bis liegt nach dem Ende des Vergleichszeitraums + Von liegt vor dem Ende
3. Vor und Bis liegt innerhalb des Vergleichszeitraums

=>
strFilter = "Personalnummer=" & Me!cbo_Mitarbeiter & " And (" & _
                "(DatumVon <= " & lngVon & " And DatumBis >= " & lngVon & ") OR " & _
                "(DatumVon <=" & lngBis & " And DatumBis >=" & lngBis & ") OR " & _
                "(DatumVon >=" & lngVon & " AND DatumBis <=" & lngBis & "))"



Ich würde die Variante nehmen, die nur prüft, ob
Bis nach dem Start des Vergleichtszeitraums liegt und Von vor dem Ende des Vergleichszeitraums. ;)
strFilter = "Personalnummer=" & Me!cbo_Mitarbeiter & " And " & _
                "DatumVon <= " & lngBis & " And DatumBis >= " & lngVon


.. ergibt die gleichen Treffer, ist aber irgendwie übersichtlicher.
Anm.: Falls in den Datumswerte auch Uhrzeiten enthalten sind, müsste der Bis-Vergleichsdatsumswert (ohne Uhrzeit) um 1 Tag erhöht und dafür nur mit < statt <= verglichen werden.

Zur graphischen Überprüfung der Logik:
(http://access.joposol.com/download/Ueberschneidungen.png)

mfg
Josef