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 ::)
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
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.
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
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?
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
Hab's versucht, gibt leider '3075' Syntaxfehler im Abfrageausdruck :(
Hallo,
dann mal mit einem kleinen Beispiel....
Gruß Oma
[Anhang gelöscht durch Administrator]
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 :(
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
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 & " ))) "
Hallo svartisya,
komme erst morgen (oder Wochenende?) zur Begutachtung...Geduld, alles wird gut ;D
Gruß Oma
Ich hab's nicht eilig, kein Problem, Du hast mir so wie so schon so viel weitergeholfen, ich danke dir vielmals! :D
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
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
Hallo!
Ich hatte leider erst jetzt Zeit zum ausprobieren: wow es funktioniert fast :) Es öffnet sich eine Messagebox die nach einem Wert für Portate.Portate frägt, aber wenn ich auf Ok klicke, zeigt das Formular schon die richtigen Ergebnisse an (mit Fragezeichen in der Spalte Portate). Ich habe versucht es selbst zu lösen, leider ohne Erfolg
Hallo Jocca
wenn mit einer Messagebox nach einem Feld gefragt wird, ist deutet das darauf hin. dass es das Feld nicht gibt bzw. der Feldname falsch geschrieben ist. Habe sowieso überlegt, was es mit der Tabelle Portate auf sich hat?
zu deinem anderen Problem:
wenn du in einem Feld einen Wert eingibst, und du in einem weiteren Datensatz im gleichen Feld den Wert als "Voreinstellung" haben möchtest, kannst du bei diesem Feld für das Ereignis: Nach Aktualisierung folgendes schreiben: (siehe auch http://www.donkarl.com?FAQ4.22 (http://www.donkarl.com?FAQ4.22))
Private Sub DeinFeldname_AfterUpdate()
Me!DeinFeldname.DefaultValue = Chr$(34) & Me!DeinFeldname& Chr$(34)
End Sub
Gruß Oma
Du hast recht! Jetzt habe ich wieder was dazu gelernt ;D, ich hab's falsch geschrieben, sollte Portata sein (auf Deutsch Gang / Kategorie). Danke vielmals für die Grosse Hilfe, jetzt ist alles perfekt!! :) :)