Neuigkeiten:

Ist euer Problem gelöst, dann bitte den Knopf "Thema gelöst" drücken!

Mobiles Hauptmenü

Suchformular - Mehrfachauswahl Listenfeld

Begonnen von svartisya, Februar 14, 2012, 16:11:03

⏪ vorheriges - nächstes ⏩

svartisya

Hallo zusammen!  :)

Ich habe vor einiger Zeit ein DB für meine Rezepte erstellt und da die Rezepte immer mehr werden, würde ich gerne ein neues Suchformular erstellen, aber ich bin leider mit VBA noch ziehmlich am Anfang und brauche etwas Hilfe.
Ich habe die folgenden Tabellen in einer n:m Beziehung:

Rezepte                  Zutaten-Rezepte        Zutaten

IDRezept                 IDRezept                    IDZutat
Rezept                    IDZutat                       Zutat
Zubereitung            IDZutRez
...                            ...

Im Suchformular habe ich ein Mehrfachauswahl Listenfeld das alle Zutaten anzeigt. Die Suche sollte mir dann die Ergebnisse in einem Endlosformular zeigen. Wenn ich z.B. Eier, Butter und Mehl im Listenfeld auswähle, möchte ich dass alle Rezepte für die man diese Zutaten braucht, angezeigt werden. Ist das möglich?
Ich habe so etwas auf einem italienischen Forum schon gesehen, aber da wurde leider nie die Lösung geschrieben.
Bis jetzt ist es mir mit einer Zutat gelungen, aber wenn ich mehrere Zutaten auswähle, ird jedes Rezept drei- oder viermal angezeigt:

Private Sub Suche_Click()
   
    Dim strSelection As String, varItem As Variant
    Dim strSQL As String
    For Each varItem In Me!Zutatenliste.ItemsSelected
         strSelection = strSelection & Me!Zutatenliste.ItemData(varItem) & ","
    Next varItem
    If Len(strSelection) = 0 Then
          MsgBox "Mindestens eine Zutat wählen!" , vbExclamation, "Achtung!"
          Exit Sub
   End If
   strSelection = Left(strSelection, Len(strSelection) - 1)
    strSQL = "IDZutat IN (" & strSelection & ") "
   DoCmd.OpenForm "Suchergebnisse", acNormal, , strSQL
   DoCmd.Close acForm, "Suche"
Exit_Suche_Click:
   Exit Sub
End Sub


Ich hoffe, ich war klar genug, mein deutsch ist leider nicht so perfekt  ::)

oma

Hallo svartisya,

ich denke mit deinem SQL-String ist das geschilderte Ergebnis richtig. In der Tabelle Zutaten_Rezepte stehen zu einem Rezept mehrere Zutaten, d. h. richtigerwiese zu einem Rezept mehrere Datensätze mit einer IDRezept u. verschiedene IDZutaten, so dass bei 2 verschiedene Zutaten auch  2 Datensatze mit einer IDRezept erscheinen wird.
Ein möglicher Weg wäre evt:

Select Distinct IDRezept 
From Zutaten_Rezepte 
Where IDZutat In (1,2)


d. h. erst über eine Abfrage nur die IDRezepz ermitteln u. diese dann zur Datenquelle des Ergebnisformulars benutzen.

Gruß Oma


nichts ist fertig!

DF6GL

Hallo,

vermutlich wird nicht "wo kommt überall Eier, Butter oder Mehl vor"  gemeint sein, sondern eher:

"wo kommen (mindestens)   Eier, Butter und Mehl zusammen vor"


so dass mit Gruppierung und Having Count(*)  = 3   (in diesem Fall der 3 Zutaten) gearbeitet werden müsste.
Viele Grüße vom Bodensee
Franz, DF6GL

Hilfestellung:  http://www.access-o-mania.de/forum/index.php?topic=6969.msg118738#msg118738

Links und Tipps:
1.   http://v.hdm-stuttgart.de/~riekert/lehre/db-kelz/
1a. http://www.tinohempel.de/info/info/datenbank/normalisierung.htm
1b. https://support.office.com/de-de/article/Grundlagen-des-Datenbankentwurfs-eb2159cf-1e30-401a-8084-bd4f9c9ca1f5#bmterms
2.   http://www.donkarl.com
3.   https://web.archive.org/web/20201201233522/http://www.dbwiki.net/
4.   http://www.access-tutorial.de/
5.   http://www.tty1.net/smart-questions_de.htm
6.   http://access.joposol.com/accept

Last but not least:   < F1 > für Hilfe
;) Learning by doing not by spoon-feed ;)

Tipp: Find and Replace for Access

oma

Hallo,

@Franz. das ist natürlich auch möglich. aber im Code von svartisya war:    strSQL = "IDZutat IN (" & strSelection & ")   und das hieße Eier oder Butter oder Mehl.

naja, sie/er wird sich dann ja äußern.

Gruß Oma
nichts ist fertig!

svartisya

Zitat von: DF6GL am Februar 14, 2012, 19:49:09
Hallo,

vermutlich wird nicht "wo kommt überall Eier, Butter oder Mehl vor"  gemeint sein, sondern eher:

"wo kommen (mindestens)   Eier, Butter und Mehl zusammen vor"


so dass mit Gruppierung und Having Count(*)  = 3   (in diesem Fall der 3 Zutaten) gearbeitet werden müsste.

ja, genau so habe ich das gemeint: "wo kommen (mindestens)   Eier, Butter und Mehl zusammen vor".
Ich hab noch nicht ganz kapiert wo genau ich diese Gruppierung in den Code einbauen muss, aber ich hab mir gedacht, dass die Anzahl von ausgewählten Zutaten wahrscheinlich nicht immer dieselbe ist, also habe ich schon mal diese Funktion dazugeschrieben (bedanke mich beim Autoren ;D):

Function CountSelected_MultiSelect() As Long

    Dim varItm As Variant
    Dim lngCount As Long
    Dim ctl As Control
    Set ctl = Me.Zutatenliste
   
    For Each varItm In ctl.ItemsSelected
    lngCount = lngCount + Abs(ctl.Selected(varItm))
    Next varItm
   
    CountSelected_MultiSelect = lngCount
   
End Function


also müsste es dann  Having Count(*)  = CountSelected_MultiSelect   sein. Ist das richtig?

oma

Hallo svartisya,

ein Vorschlag: mache das Listenfeld zur Auswahl in ein Formularkopf und die Ergebnisdaten in den Detailbereich des Formulars.
Wenn die Rezepte die ausgewählten Zutaten mindestens erhalten sollen, sollte folgendes funktionieren:

Private Sub Suche_Click()
   
   Dim strSelection As String, varItem As Variant
   Dim strSQL As String, K As Long
   For Each varItem In Me!Zutatenliste.ItemsSelected
        strSelection = strSelection & Me!Zutatenliste.ItemData(varItem) & ","
        K = K + 1
   Next varItem
   
   If Len(strSelection) = 0 Then
         MsgBox "Mindestens eine Zutat wählen!", vbExclamation, "Achtung!"
         Exit Sub
   End If
   strSelection = Left(strSelection, Len(strSelection) - 1)

   
   strSQL = "SELECT IDRezept, Rezept  FROM Rezepte WHERE IDRezept"
   strSQL = strSQL & " IN(SELECT DISTINCT IDRezept FROM Zutaten_Rezepte WHERE IDZutat IN (" & strSelection & ")"
   strSQL = strSQL & " GROUP BY Zutaten_Rezepte.IDRezept HAVING (((Count(Zutaten_Rezepte.IDRezept))=" & K & " ))) "
 

   Me.Form.RecordSource = strSQL
 
End Sub



Gruß Oma



nichts ist fertig!

svartisya

Hab's versucht, gibt leider '3075' Syntaxfehler im Abfrageausdruck  :(

oma

Hallo,

dann mal mit einem kleinen Beispiel....

Gruß Oma

[Anhang gelöscht durch Administrator]
nichts ist fertig!

svartisya

danke, in deinem beispiel funktioniert es :)
ich hab's auch geschafft die ergebnisse in einem anderen formular zu öffnen, anstatt   Me.Form.RecordSource = strSQL   hab ich es so gemacht:     DoCmd.OpenForm "Suchenergebnisse1"
    Forms!Suchenergebnisse1.RecordSource = strSQL
und es funktioniert.

Wenn ich das gleiche jetzt in meinem DB mache, funktioniert es leider nicht. Bestimmt liegt das problem daran, dass mein Ergebnissformular zu kompliziert ist, da es nicht nur das Rezept zeigt, sondern auch Bild, Kategorie, Schwierigkeit und Zeit (das heist meine Abfrage basiert auf drei verschiedenen tabellen). Ich muss es wohl etwas einfacher machen  :(

oma

Hallo,

nein brauchst du nicht. Du musst dann eben den SQL-String entsprechend anpassen!

In der ersten Zeile:  strSQL = "SELECT IDRezept, Rezept  FROM Rezept     müssen dann die andren Tabellen mit entspr. Join und Felder zugefügt werden.

Gruß Oma
nichts ist fertig!

svartisya

Hallo!
Ich glaube ich habe mit meinen ganzen Experimenten einen ziehmlichen Durcheinnder mt meiner Abfrage gemacht  ;D. Ich habe verschiedene Versionen ausprobiert, aber bekomme entweder Syntax Fehler, oder Fehlender Operator. Hier z.B. ist es Syntax Fehler, abe ich weis nicht was falsch ist (ist leider auf italienisch, da ich das DB in Italien brauche):
    strSQL = "SELECT Ricette.IDRicetta, Ricette.Ricetta, Ricette.Preparazione, Ricette.Porzioni, Ricette.Note, Ricette.IDPortate AS Ricette_IDPortate, Ricette.Calorie, Ricette.Difficoltà, Ricette.Immagine, Ricette.[Tempo Cottura], Portate.IDPortate AS Portate_IDPortate, Portate.Portata, Ricette.[Tempo Preparazione] FROM Portate INNER JOIN Ricette ON Portate.[IDPortate] = Ricette.[IDPortate] WHERE Ricette.IDRicetta"
strSQL = strSQL & " IN(SELECT DISTINCT IDRicetta FROM Ricetta-Ingredienti WHERE IDIngredienti IN (" & strSelection & ")"
strSQL = strSQL & "GROUP BY Ricetta-Ingredienti.IDRicetta HAVING (((Count(Ricetta-Ingredienti.IDRicetta))=" & K & " ))) "

oma

Hallo svartisya,

komme erst morgen (oder Wochenende?) zur Begutachtung...Geduld, alles wird gut ;D

Gruß Oma
nichts ist fertig!

svartisya

Ich hab's nicht eilig, kein Problem, Du hast mir so wie so schon so viel weitergeholfen, ich danke dir vielmals!  :D

oma

Hallo,

mal auf die schnelle; versuche es mal mit:

strSQL = "SELECT Ricette.IDRicetta, Ricette.Ricetta, Ricette.Preparazione, Ricette.Porzioni, Ricette.Note, Ricette.IDPortate AS Ricette_IDPortate, "
strSQL = strSQL & " Ricette.Calorie, Ricette.Difficoltà, Ricette.Immagine, Ricette.[Tempo Cottura], Portate.IDPortate AS Portate_IDPortate, Portate.Portata, "
strSQL = strSQL & " Ricette.[Tempo Preparazione] FROM Portate INNER JOIN Ricette ON Portate.[IDPortate] = Ricette.[IDPortate] WHERE Ricette.IDRicetta"
strSQL = strSQL & " IN(SELECT DISTINCT IDRicetta FROM [Ricetta-Ingredienti] WHERE IDIngredienti IN (" & strSelection & ")"
strSQL = strSQL & " GROUP BY [Ricetta-Ingredienti].IDRicetta HAVING (((Count([Ricetta-Ingredienti].IDRicetta))=" & K & " )))"


Gruß Oma
nichts ist fertig!

oma

Hallo,

hier auf italienisch ;D, so sollte es gehen:

Private Sub Suche_Click()
   
    Dim strSelection As String, varItem As Variant
    Dim strSQL As String, K As Long
    For Each varItem In Me!Zutatenliste.ItemsSelected
         strSelection = strSelection & Me!Zutatenliste.ItemData(varItem) & ","
         K = K + 1
    Next varItem
   
    If Len(strSelection) = 0 Then
          MsgBox "Mindestens eine Zutat wählen!", vbExclamation, "Achtung!"
          Exit Sub
    End If
    strSelection = Left(strSelection, Len(strSelection) - 1)

    strSQL = "SELECT Ricette.IDRicetta, Ricette.Ricetta, Ricette.Preparazione, Ricette.Porzioni, Ricette.Note,"
    strSQL = strSQL & " Ricette.IDPortate, Ricette.Calorie, Ricette.Difficolta, Ricette.Immagine,"
    strSQL = strSQL & " Ricette.[Tempo Cottura],Ricette.[Tempo Preparazione], Portate.IDPortate, Portate.Portate"
    strSQL = strSQL & " FROM Ricette INNER JOIN Portate ON Ricette.IDPortate = Portate.IDPortate"
    strSQL = strSQL & " WHERE Ricette.IDRicetta IN(SELECT DISTINCT IDRicetta FROM [Ricetta-Ingredienti] WHERE IDIngredienti IN (" & strSelection & ")"
    strSQL = strSQL & " GROUP BY [Ricetta-Ingredienti].IDRicetta HAVING (((Count([Ricetta-Ingredienti].IDRicetta))=" & K & " )))"
   
    Me.Form.RecordSource = strSQL
   
End Sub


Gruß Oma
nichts ist fertig!