Hallo liebe Community.
vor Jahren war ich mal ziemlich gut in VBA Programmierung.. doch nun, da nicht mehr gebraucht eher peinlich, was ich da so zusammen schustere.. Deshalb dachte ich, lass doch mal ChatGPT, welches ja in aller Munde ist und gelobt wird eine eigentlich einfache Aufgabe lösen, hier was ich geschrieben habe:
Ich habe eine Access Datenbank in welcher Bestellungen von Restaurants erfasst werden. Nun möchte ich Abrechnungen über die Umsätze von START-Datum bis END-Datum erstellen.
Es gibt eine Tabelle "10Restaurants" in welchen alle Restaurants aufgelistet sind mit Adresse usw. In der Tabelle gibt es auch ein Feld "Bar". Dort soll das Total der Umsätze im ausgewählten Zeitraum eingetragen werden. Zudem gibt es ein Feld "RestID"
In der zweiten Tabelle "02UmsatzArchiv" sind die Umsätze pro Bestellung eingetragen. Im Feld "Total". Zudem gibt es ein Feld "ODate", das ist das Datum des Umsatzes und ein Feld "RestaurantID", welche mit der ID des Restaurants "RestID" verlinkt wird.
Hier das Resultat:
Private Sub Befehl40_Click()
Dim db As DAO.Database
Dim rsRestaurants As DAO.Recordset
Dim rsRevenue As DAO.Recordset
Dim startDate As Date
Dim endDate As Date
Dim restaurantID As Long
Dim restaurantName As String
Dim totalRevenue As Double
' Prompt user for start and end dates
startDate = InputBox("Please enter the start date for the report:", "Start Date")
endDate = InputBox("Please enter the end date for the report:", "End Date")
' Open database and set references to the two tables
Set db = CurrentDb
Set rsRestaurants = db.OpenRecordset("10Restaurants")
Set rsRevenue = db.OpenRecordset("02UmsatzArchiv")
' Loop through each restaurant and calculate total revenue
rsRestaurants.MoveFirst
Do Until rsRestaurants.EOF
' Get the current restaurant ID and name
restaurantID = rsRestaurants!restID
restaurantName = rsRestaurants!RestName
' Reset the total revenue
totalRevenue = 0
' Find all revenue records for the current restaurant within the date range
rsRevenue.FindFirst "ODate >= #" & startDate & "# AND ODate <= #" & endDate & "# AND RestaurantID = " & restaurantID
If Not rsRevenue.NoMatch Then
' Add up all the revenue for the restaurant in the date range
Do Until rsRevenue.EOF Or rsRevenue!restaurantID <> restaurantID
totalRevenue = totalRevenue + rsRevenue!Total
rsRevenue.MoveNext
Loop
End If
' Update the "Bar" field in the "10Restaurants" table with the total revenue
rsRestaurants.Edit
rsRestaurants!Bar = totalRevenue
rsRestaurants.Update
' Move to the next restaurant
rsRestaurants.MoveNext
Loop
' Clean up
rsRestaurants.Close
rsRevenue.Close
Set rsRestaurants = Nothing
Set rsRevenue = Nothing
Set db = Nothing
MsgBox "The revenue report has been created!", vbInformation
End Sub
Und führt zu einem Fehler:
Operation wird für diesen Objekttyp nicht unterstützt
in der Zeile:
rsRevenue.FindFirst "ODate >= #" & startDate & "# AND ODate <= #" & endDate & "# AND RestaurantID = " & restaurantID
aus meiner Sicht stimmt da was mit der Verknüpfung von RestaurantID und restaurantID nicht..
Lasst uns beweisen, dass Menschen immer noch schlauer sind, als angebliche AI..
Danke für Feedback
LG
Hallo!
Tipp für die Fehlersuche:
dim FilterString as String
FilterString "ODate >= #" & startDate & "# AND ODate <= #" & endDate & "# AND RestaurantID = " & restaurantID
debug.Print FilterString
stop ' die Ausgabe von Debug.Print im Direktbereich prüfen
rsRevenue.FindFirst FilterString
Gruß
Josef
@ElDonJola, ich möchte dir mein
VBA-SQL-String Tutorial empfehlen. Zum konkreten Problem dürfte der Teil
SQL-Strings mit Datumswerten (https://codekabinett.com/rdumps.php?Lang=1&targetDoc=vba-sql-string-tutorial#sql-strings-datum) hilfreich sein.
Danke für den Link und Hinweis, also sollte die Zeile so funktionieren?
rsRevenue.FindFirst "ODate >= #" & Format(startDate, "yyyy-mm-dd") & "# AND ODate <= #" & Format(endDate, "yyyy-mm-dd") & "# AND RestaurantID = " & restID
?
Zitat von: ElDonJola am Februar 10, 2023, 18:02:57Danke für den Link und Hinweis, also sollte die Zeile so funktionieren?
Ja, ich denke schon. - Du bist in der besten Position, um das auszuprobieren.
ZitatLasst uns beweisen, dass Menschen immer noch schlauer sind, als angebliche AI
Denkfrage: Hast Du eine deutschsprachige AI bemüht, die gedanklich auch mit deutschen Regionaleinstellungen arbeitet?
Solch eine Frage sollte dem eigenen Intellekt entspringen, die richtige Antwort natürlich auch.
Zitat von: ebs17 am Februar 10, 2023, 19:29:47Hast Du eine deutschsprachige AI bemüht, die gedanklich auch mit deutschen Regionaleinstellungen arbeitet?
Auch ein
US-englischsprachiger Entwickler (bzw. AI) sollte berücksichtigen, dass Menschen mit anderen Datumsformaten existieren.
Zitat von: PhilS am Februar 10, 2023, 18:46:04Zitat von: ElDonJola am Februar 10, 2023, 18:02:57Danke für den Link und Hinweis, also sollte die Zeile so funktionieren?
Ja, ich denke schon. - Du bist in der besten Position, um das auszuprobieren.
Leider krieg ich immer noch diese nervige Fehlermeldung...
Zitat von: ebs17 am Februar 10, 2023, 19:29:47ZitatLasst uns beweisen, dass Menschen immer noch schlauer sind, als angebliche AI
Denkfrage: Hast Du eine deutschsprachige AI bemüht, die gedanklich auch mit deutschen Regionaleinstellungen arbeitet?
Solch eine Frage sollte dem eigenen Intellekt entspringen, die richtige Antwort natürlich auch.
Ja, zumindest wird das behauptet bei chat.openai.com...
Zitat von: Josef P. am Februar 10, 2023, 16:03:30Hallo!
Tipp für die Fehlersuche:
dim FilterString as String
FilterString "ODate >= #" & startDate & "# AND ODate <= #" & endDate & "# AND RestaurantID = " & restaurantID
debug.Print FilterString
stop ' die Ausgabe von Debug.Print im Direktbereich prüfen
rsRevenue.FindFirst FilterString
Gruß
Josef
Sieht doch eigentlich OK aus?
ODate >= #2023-01-01# AND ODate <= #2023-02-01# AND RestaurantID = 234116
Oder müsste das Datum anderes Format haben?
ZitatOperation wird für diesen Objekttyp nicht unterstützt
Die Meldung scheint mit Filterkriterien nichts zu tun zu haben, sondern mit dem FindFirst an sich. Gibt es überhaupt Datensätze im Recordset, ist ein Suchen durch irgendeine Einstellung untersagt - solche Fragen müsste man sich stellen und beantworten.
Aber eigentlich: Du bildest eine Summe aus den Inhalten von Total und vertraust in der Schleife dazu auf eine passende Sortierung.
Mit einem DSum und dem gleichen Filter bekommst Du die Summe unmittelbar und könntest so auf das zweite Recordset mit dem problematischen FindFirst ganz verzichten.
Also frage mal die AI, warum eine Abfrage besser ist als eine VBA-Schleife.
Zusätzlich stellt sich die Frage, warum Summen, also berechnete Werte, in eine Tabelle gespeichert und aktualisiert werden. Die Speicherung von Berechnungsergebnissen wird man wegen des Potentials an Datenanomalien wegen Anfügen, Löschen und Editieren unterlassen oder besonders begründen + absichern.
Obendrauf: In Access kann man sehr einfach Formulare mit einer hohen Funktionalität erzeugen. Da ist bereits ein Denken an eine InputBox armselig. Bei dieser musst Du nachdenken, was genau (Datentyp und Inhalt) weitergegeben wird.
Hallo!
Die Meldung hängt vom Recordsettyp ab. Nicht jeder unterstützt FindFirst.
Set rsRevenue = db.OpenRecordset("02UmsatzArchiv") ' .. ist 02UmsatzArchiv eine Tabelle? =>
debug.print rsRevenue.Type, dbOpenTable
Set rsRevenue = db.OpenRecordset("02UmsatzArchiv", dbOpenTable)
Set rsRevenue = db.OpenRecordset("02UmsatzArchiv", dbOpenForwardOnly)
Set rsRevenue = db.OpenRecordset("02UmsatzArchiv", dbOpenDynaset)
Daher lieber immer den Type-Parameter explizit angeben.
Gruß
Josef
Aus der Hilfe:
ZitatRecordset.FindFirst (Methode)
Sucht den ersten Datensatz in einem Recordset-Objekt vom Typ Dynaset oder Snapshot, der den angegebenen Kriterien entspricht
sowie Recordset-Objekt (DAO) (https://learn.microsoft.com/de-de/office/client-developer/access/desktop-database-reference/recordset-object-dao):
ZitatWenn Sie in einem Microsoft Access-Arbeitsbereich keinen type angeben, versucht DAO, den Recordset-Typ mit den meisten verfügbaren Funktionen beginnend mit "table" zu erstellen. Falls dieser Typ nicht verfügbar ist, probiert DAO ein "dynaset"-, dann ein "snapshot"- und schließlich ein "forward-only"- Recordset-Objekt aus.
...
Wenn Sie ein Recordset -Objekt mit einem nicht verknüpften TableDef -Objekt in einem Microsoft Access-Arbeitsbereich erstellen, werden Recordset -Objekte vom "table"-Typ erstellt.
Also: Der Standardtyp (verwendet ohne eigene Angabe dazu) ist bei einer internen Tabelle dbOpenTable, bei einer verknüpften Tabelle dbOpenDynaset.
OpenTable kann kein FindFirst ausführen, kennt aber die schnelle Seek-Methode.
ZitatRecordset-Typ mit den meisten verfügbaren Funktionen
Meiste Funktionen heißt aber auch höherer Verwaltungsaufwand. Das Ermöglichen von Schreibvorgängen erfordert mehr Aufwand als wenn nur einfach einmal gelesen werden soll. Weniger Aufwand heißt auch potentiell höhere Performance.
Aber es bleibt dabei: Warum nicht gleich Abfrage, wenn wie hier möglich?
Also wenn jemand hier einen lauffähigen Code hinkriegt, ist mir diee durchaus ein paar Kaffees und mehr wert. Nebst dem Beweis, dass openAI noch nicht viel mit AI sondern mehr Zusammensuchen von Codeschnipseln zu tun hat...
Soll man Deinen Beitrag jetzt so verstehen, dass alle fachlichen Hinweise umsonst waren?
Nein, das wäre falsch. Ich bin über all die Tipps sehr dankbar. Habe aber erkannt, dass meine VBA Kenntnisse wirklich sehr angestaubt sind. Daher probiere ich es nun -wie auch als Tipp genannt- mit einer gruppierten Abfrage.. dennoch bin ich neugierig, wie ein lauffähiger Code aussehen würde. Lerne viel aus geschriebenen Codes, da ich so meine erste Schritte in den 80ern im Programmieren gemacht hab, stundenlanges abschreiben von Basic-Codes .-)
Leider bin ich auch mit SQL nicht so erfolgreich, dies mein Code:
SELECT 10Restaurants.RestID, PayMethod, Sum(02UmsatzArchiv.Total) AS Umsatz
FROM 10Restaurants INNER JOIN 02UmsatzArchiv ON 10Restaurants.RestID = 02UmsatzArchiv.RestaurantID
WHERE (((02UmsatzArchiv.ODate) >= #01/01/2023#) AND ((02UmsatzArchiv.ODate) <= #01/02/2023#))
GROUP BY 10Restaurants.RestID, PayMethod;
Resultiert in: Syntax Fehler (fehlender Operator) in Abfrageausdruck 10Restaurants.RestID