Neuigkeiten:

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

Mobiles Hauptmenü

Rangliste berechnen

Begonnen von Michael Wulf, Juli 24, 2016, 19:23:38

⏪ vorheriges - nächstes ⏩

Michael Wulf

Guten morgen zusammen,

ich habe nachstehendes Problem:

Ich erstelle eine Datenbank für eine Turnierverwaltung. Es gibt eine Tabelle "Turnier" in der die Teilnehmer und deren Ergebisse verwaltet werden. Hierunter sind u.a. die Felder  "Summe Runden" und "Rangber".

Über eine Abfrage werden bestimmte Klassen und Gruppen gefiltert. Die Abfrage heißt ABF_Urkunden. Ich möchte nun das Feld "Rangber" automatisch mit dem entsprechenden Rang füllen um Urkunden drucken zu können. Dazu habe ich nachstehende Funktion gefunden:


Public Function RangSetzen()

Dim db As Database
Dim rs As Recordset
Dim z As Long

    Set db = CurrentDb()
    Set rs = db.openrecordset("SELECT * FROM ABF_Urkunden ORDER BY [Summe Runden];", dbopendynaset)
   
    Do Until rs.EOF
        z = z + 1
        rs.Edit
            rs!Rangber = z
        rs.Update
        rs.MoveNext
    Loop
   
    rs.Close
    db.Close
   
End Function


Über eine Schaltfläche im Hauptformular wird die Berechnung durchgeführt um im Unterformular die neu berechnete Abfrage zu zeigen.

Dim a As Variant

    a = RangSetzen()
    MsgBox "VBA-Aktualisierung wurde durchgeführt!", 48
    Me.Requery



Beim Ausführen erhalte ich die nachstehende Fehlermeldung:

Laufzeitfehler 3061

Es wurden 4 Parameter erwartet, aber es wurden zuwenig Parameter übergeben.

Kann mir bitte jemand helfen ? Ich nutze Access 2010

Vielen Dank

ebs17

Die Fehlermeldung ist typisch für nicht verfügbare Felder und Tabellen/Abfragen sowie für nicht auflösbare Parameter (Formularbezüge?).
Wie lautet die vollständige SQL-Anweisung zu ABF_Urkunden?
Mit freundlichem Glück Auf!

Eberhard

Michael Wulf

Danke dass Du dir das anschaust. Hier der Code für die Abfrage:

SELECT Turnier.Turniername, Turnier.Teilnehmer, Turnier.[Summe Runden], Turnier.[Summe X], Turnier.Klasse_Grob_FS, Turnier.Bogenklasse_FS, Turnier.Altersklasse_FS, Turnier.Rangber
FROM Turnier
WHERE (((Turnier.Turniername)=[Formulare]![Hauptmenü]![Auswahl_Turnier]) AND ((Turnier.Klasse_Grob_FS)=[Formulare]![FRM_Urkunden]![Kombinationsfeld1]) AND ((Turnier.Bogenklasse_FS)=[Formulare]![FRM_Urkunden]![Kombinationsfeld3]) AND ((Turnier.Altersklasse_FS)=[Formulare]![FRM_Urkunden]![Kombinationsfeld5]))
ORDER BY Turnier.[Summe Runden] DESC;


Kann es sein, das die Funktion nicht in eine Abfrage schreiben kann ?

ebs17

Du verwendest in Deiner Abfrage direkte Formularbezüge in der Filterung. Die sind schnell mal kritisch. Wenn Du die Abfrage in Access öffnest (Doppelklick im Navigationsbereich, OpenQuery u.a.), dann spielt Access mit und macht die Werte der Formularfelder verfügbar.
In Deiner Funktion wird die Abfrage jedoch direkt an die Jet-Engine übergeben (über das Recordset). Diese kennt keine Formulare und deren Objekte und kann so den Inhalt nicht auswerten. Da kommt dann eben die Nachfrage.
Siehe auch Ein Parameter wurde erwartet
Da gibt es auch Lösungsvorschläge (Eval, echte Parameterabfrage).

Eine weitere Möglichkeit wäre, unmittelbar die SQL-Anweisung der Abfrage einzusetzen und die Parameter dynamisch einzusetzen, wobei die Parameter sinnvollerweise als Argumente an die Funktion zu übergeben wären, etwa ...
Public Function RangSetzen(ByVal Arg1 As String, ...)
   Dim sSQL As String
   ' ...
   sSQL = "SELECT * FROM Turnier" & _
         " WHERE Turniername = '" & Arg1 & "' AND Klasse_Grob_FS = ..."
   Set rs = db.Openrecordset(sSQL, dbOpenDynaset)
   ' ...
End Function

Hier werden die Variablen/Argumente vor dem Zusammensetzen der SQL-Anweisung ausgewertet, so dass dann die SQL-Anweisung fertig an die Jet-Engine übergeben wird.

Alternativ könnte man auch an eine komplette Abfragelösung denken: Laufende Nummer/Summe in Abfragen
Mit freundlichem Glück Auf!

Eberhard

Michael Wulf

Vielen Dank.

An die angesprochene Lösung habe ich auch schon gedacht.

Wie baue ich diese denn in die ABF_Urkunden ein ? Einfach hinten anfügen ?

SELECT Turnier.Turniername, Turnier.Teilnehmer, Turnier.[Summe Runden], Turnier.[Summe X], Turnier.Klasse_Grob_FS, Turnier.Bogenklasse_FS, Turnier.Altersklasse_FS, Turnier.Rangber
FROM Turnier
WHERE (((Turnier.Turniername)=[Formulare]![Hauptmenü]![Auswahl_Turnier]) AND ((Turnier.Klasse_Grob_FS)=[Formulare]![FRM_Urkunden]![Kombinationsfeld1]) AND ((Turnier.Bogenklasse_FS)=[Formulare]![FRM_Urkunden]![Kombinationsfeld3]) AND ((Turnier.Altersklasse_FS)=[Formulare]![FRM_Urkunden]![Kombinationsfeld5]))
ORDER BY Turnier.[Summe Runden] DESC;


und dann

LaufNummer: (Select Count (*) FROM [ABF_Urkunden] as Temp WHERE [Temp].[Summe Runden] < [ABF_Urkunden].[Summe Runden])+1

Wenn ich das mache kommt es zu einem Zirkelbezug

Danke Michael

MaggieMay

Hi,

du musst dich im Sub-Select auf die Tabelle "Turnier" beziehen.

PS:
Diese Art der Rangermittlung ist deiner Prozedur schon deshalb vorzuziehen, weil dabei gleiche Ergebnisse und somit auch gleriche Plätze berücksichtigt werden.
Freundliche Grüße
MaggieMay

Michael Wulf

Habe den nachfolgenden Code eingeführt:

LaufNummer: (Select Count (*) FROM [Turnier] as Temp WHERE [Temp].[Summe Runden] > [Turnier].[Summe Runden])+1

Das führt zu dem im Anhang dargestellten Ergebnis. Ich möchte aber eine bei 1 beginnende steigende durchgehende Nummerierung.

Sorry, aber wir arbeiten uns ran  ;)

Danke Michael

MaggieMay

Du musst natürlich auch die übrigen Kriterien mit hinzunehmen:
WHERE [Temp].[Summe Runden] > [Turnier].[Summe Runden] AND
Turnier.Turniername=Temp.Turniername AND Turnier.Klasse_Grob_FS=Temp.Klasse_Grob_FS AND Turnier.Bogenklasse_FS=Temp.Bogenklasse_FS AND Turnier.Altersklasse_FS=Temp.Altersklasse_FS
Freundliche Grüße
MaggieMay

Michael Wulf

Leider kann ich euch nicht umarmen. DANKE. Es funktioniert.

:) :-*