Neuigkeiten:

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

Mobiles Hauptmenü

Probleme mit Formular: Laufzeitfehler 2001

Begonnen von bethlis, September 27, 2011, 09:29:23

⏪ vorheriges - nächstes ⏩

bethlis

Hallo,

ich komme mit meiner DB-Anwendung nicht weiter...

Folgendes Szenario:
Ich habe 2 Tabellen Mitarbeiter und Kunde. Diese sind über den Fremdschlüssel 'WirdBetreutVon' miteinander verknüpft.
Ich habe ein Formulart erstellt, mit dem man neue Kunden in die Tabelle aufnehmen kann und den Mitarbeiter, der den Kunden betreut eingibt. Wenn der Mitarbeiter schon manuell angelegt wurde funktioniert das wunderbar.
Ich wollte jetzt an das textfeld in dem der Mitarbeiter eingegeben wird eine Abfrage knüpfen, ob der Mitarbeiter in der Tabelle schon vorhanden ist, und wenn nicht sollte ein weiteres Formular aufgehen in dem man den neuen Mitarbeiter anlegen kann und anschließend wieder auf das Kundenformular zurückkommt.

Leider kommt dann folgender Fehler: Laufzeitfehler 2001: Sie haben die vorherige Aktion abgebrochen

Hier der komplette Code:
Private Sub cmdAbbrechen_Click()
   
    If MsgBox("Eingabe Abbrechen?", Buttons:=vbYesNo, Title:="Zutateneingabe") = vbYes Then
        DoCmd.Close
    Else:
        Screen.PreviousControl.SetFocus
    End If
   
End Sub

Private Sub cmdSpeichern_Click()

    On Error GoTo err_cmdSpeichern

        Dim db As Database
        Dim rstKunde As Recordset

        On Error GoTo err_cmdSpeichern

        Set db = CurrentDb()
        Set rstKunde = db.OpenRecordset("tblKunden")
   
    With rstKunde
        .AddNew
        !Vorname = txtVorname
        !Nachname = txtNachname
        !email = txteMail
        !wirdBetreutVon = txtBetreuer
        .Update
        .Close
    End With
   
end_CmdSpeichern:
    DoCmd.Close
    Exit Sub
   
err_cmdSpeichern:
    MsgBox Err.Description
    Resume end_CmdSpeichern
   
End Sub

Function testMitarbeiter(txtBetreuer As String) As Boolean

        If DLookup("[MitarbeiterNr]", "tblMitarbeiter", "[MitarbeiterNr] = Me!txtBetreuer") Then
            DoCmd.CancelEvent
        Else
            If MsgBox("Der gewünschte Mitarbeiter exisitert noch nicht. Soll der datensatz in die Tabelle `Mitarbeiter` eingefügt werden?", Buttons:=vbYesNo, Title:="Mitarbeiter nicht vorhanden") = vbYes Then
                DoCmd.OpenForm "Neuer Mitarbeiter"
            Else
                DoCmd.Close
            End If
        End If

End Function

Private Sub txtBetreuer_AfterUpdate()
   
    Dim bolMitarbeiterVorhanden As Boolean
   
    bolMitarbeiterVorhanden = testMitarbeiter(txtBetreuer)
   
End Sub


Der Fehler kommt in dieser Zeile: If DLookup("[MitarbeiterNr]", "tblMitarbeiter", "[MitarbeiterNr] = Me!txtBetreuer") Then


Kann mir irgendjemand sagen, was ich falsch mache??
Vielen Dank schonmal im vorraus!

Grüße
bethlis

Maxel

#1
Hallo,

If DLookup("MitarbeiterNr", "tblMitarbeiter", "MitarbeiterNr = " & txtBetreuer) Then

würde funktionieren, sofern MitarbeiterNr und txtBetreuer Zahlen sind. Allerdings übergibst Du der Funktion txtBetreuer als String, dann muss es heißen

If DLookup("MitarbeiterNr", "tblMitarbeiter", "MitarbeiterNr = '" & txtBetreuer & "'") Then

Der Bezug Me! ist falsch, wenn Du den Wert als Parameter in der Funktioin mitführst. Die Feldbezeichnung MitarbeiterNr ist irreführend, wenn dort Text drin steht.
Viele Grüße
Maxel

bethlis

wunderbar!!!
wenn ich txtBetreuer (muss ich noch umbenennen...  :-\ ) als Zahl deklariere passts!!!

Dankeschön für die schnelle Antwort!

Aber warum darf ich das nicht mit !Me machen?? (...ich will auch verstehen, warums jetzt klappt)

Maxel

Wenn Du auf das Formularfeld txtBetreuer Zugriff hast (das Formular also geöffnet ist), benötigst Du den Parameter txtBetreuer in der Funktion nicht. Und wenn dieser Parameter die gleiche Bezeichnung wie das Textfeld hat, kommt es wahrscheinlich zum Crash.
Viele Grüße
Maxel

MzKlMu

#4
Hallo,
Me! sollte sehr wohl verwendet werden. Me! stellt den Bezug auf das aktuell geöffnete Formular dar. Erst mit Me! ist das Feld zweifelsfrei angesprochen. Meistens geht es auch ohne Me! aber das macht es nicht richtig. Das:
If DLookup("[MitarbeiterNr]", "tblMitarbeiter", "[MitarbeiterNr] = " & Me!txtBetreuer") Then
sollte also funktionieren und wäre die richtige Version.

Me! darf nur nicht verwendet werden, wenn die Funktion als Steuerelementinhalt verwendet wird. Also =DomWert(....).

Auch bei dem Präfix txt scheiden sich die Geister. Üblicherwiese setzt man vor die Feldnamen in einem Formular ein txt unabhängig ob Zahl oder Text. Es ist zweckmäßig wenn sich Feldname und Steuerelementinhalt unterscheiden. Und an den Primärschlüssel hängt man ein ID dran und an den Fremdschlüssel noch ein _F (oder ähnlich). Primärschlüssel und Fremdschlüssel sollte man immer zweifelsfrei unterscheiden können.

Z.B.:
txtBetreuerID = Feldname im Formular
BetreuerID = Primärschlüssel
BetreuerID_F = Fremdschlüssel

Im vorliegenden Fall sollte das Tabellenfeld nicht Betreuer heisen, sondern z.B.:
BetrMitarbeiterID_F. Du ersparst Dir viel Mühe wenn Du dafür sorgst, wenn Du am Feldnamen erkennst welcher Schlüssel verwendet wird.
Gruß Klaus

Maxel

#5
OK,

ich hatte das Me! in diesem Zusammenhang als überflüssig erachtet:

Function testMitarbeiter(txtBetreuer As String) As Boolean

       If DLookup("[MitarbeiterNr]", "tblMitarbeiter", "[MitarbeiterNr] = Me!txtBetreuer") Then


Entweder das Formular ist geöffnet, dann hat man mittels Me!txtBetreuer Zugriff auf das Formularfeld; der Parameter in der Funktion ist aber überflüssig. Oder das Formular ist geschlossen, dann macht der Parameter Sinn und Me! ist falsch.  ;)
Viele Grüße
Maxel

MzKlMu

@Maxel
Du hast recht, ich hatte übersehen, dass da ein Funktion im Spiel ist, txtBetreuer ist ja ein Parameter in einer Funktuin. Da ist auch die Deklarierung als String falsch.

Sorry für die Verwirrung die ich gestiftet habe.

Aber das mit der Namensgebung stimmt wenigstens.  ;D
Gruß Klaus

bethlis

Also erstmal vielen Dank für die ausführlichen Antworten!!!

Das funktioniert jetzt soweit...
Jetzt steh ich aber vor einem neuen Problem...
wenn ich in das Huptformular Daten eingebe, die schon existieren sagt Access "Laufzeitfehler 13. Typen unverträglich" in der Zeile, in der verglichen wird, ob das entsprechende Objekt schon vorhanden ist
    If DLookup("[Firmenname]", "tblLieferant", "[Firmenname] = txtLieferantFirma") Then
'Firmenname' ist abr als text gespeichert und 'txtLieferantFirma' ebenfalls...

Woran kann das liegen??

DF6GL

Hallo,



    If DLookup("[Firmenname]", "tblLieferant", "[Firmenname] = '" & Me!txtLieferantFirma & "'") Then


hat Maxel schon beschrieben.


Weiterhin ist der Code fehlerträchtig/unbrauchbar, weil Dlookup Felddaten liefert und bei einem leeren Feld, bzw. wenn kein passender DS gefunden wird, NULL liefert, was wiederum als Ausdruck beim If-Statement zu einem Laufzeitfehler führt.

Wenn Dlookup, dann so:


  If nz(DLookup("[Firmenname]", "tblLieferant", "[Firmenname] = '" & Me!txtLieferantFirma & "'"),"") ="" Then


Alternativ wäre Dcount vom sinnlichen Inhalt ( "gibt es einen oder mehrere DS, die einem Kriterium entsprechen..") besser "zu lesen":



  If DCount("*", "tblLieferant", "[Firmenname] = '" & Me!txtLieferantFirma & "'") =0 Then



DCount hat den (theoretischen) Nachteil, das die gesamte Tabelle immer erst mal gelesen werden muss, um überhaupt die Anzahl festzustellen. Dlookup "bricht" beim Finden des ersten passenden DS ab.  (Allgemeine Nachteile der Domänenfunktionen , z. B. deren schlechte Performance, bleiben hier mal aussen vor.. )
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

bethlis

Vielen Dank für die ausführliche Erklärung!!!!!
...jetzt funktionierts!