Welches Ereignis nach Form_BeforeUpdate

Hallo,

ich habe unter Form_BeforeUpdate meine Überprüfung der Daten:
If IsNull(…) = True Then
Me.Undo
bopen = False
Exit Sub
ElseIf Len(stMeldungA) > 0 Then
bopen = True
Me!..SetFocus
DoCmd.CancelEvent
Exit Sub
End If

Unter Form_Unload sorge ich dafür, dass über das Schließen X das Formular nicht verlassen werden kann solange die Daten nicht stimmen:
If bopen = True Then
DoCmd.CancelEvent
End If

Nun bekomme ich immer wenn Len(stMeldungA) > 0 eine Meldung von Access: „Sie können diesen Datensatz momentan nicht speichern. Möglicherweise ist … Möchten Sie das Datenbankobjekt trotzdem schließen?“ Ja/Nein

Ich werde diese Meldung nicht los!

Ich habe bereits versucht:

  • diverse Ereignisse abzubrechen (ich finde jedoch keines das diese Meldung generiert)
  • Sub Form_Error: If DataErr = 2169 Then Response = acDataErrContinue (Ich komme nicht auf Me!..SetFocus zurück ohne dass die eingegebenen Daten verschwinden)
  • DoCmd.SetWarnings False (Die Meldung erscheint trotzdem)

Ich möchte nicht eine extra Schaltfläche „Schließen“ anlegen und das X ausblenden. Gibt es einen Weg die Meldung loszuwerden/auszublenden und die Auswahl „Nein“ zu setzen?

Kann mir jemand helfen?

Liebe Grüße von einer verzweifelten

Aiwala

Hallo,

Du brauchst nicht verzeifelt zu sein, Du mußt nur auf „CancelEvent“ verzichten und das „Cancel“-Argument setzen:

ich habe unter Form_BeforeUpdate meine Überprüfung der Daten:

Sub Form_BeforeUpdate( Cancel as Integer)
If IsNull(…) = True Then
Cancel =true
Me.Undo
bopen = False
Exit Sub
ElseIf nz( ME! stMeldungA,"") > „“ Then 'falls „stMeldungA“ ein Form-Textfeld Steuerelement ist
bopen = True
Me!..SetFocus
DoCmd.CancelEvent
Exit Sub
End If

End Sub

Unter Form_Unload sorge ich dafür, dass über das Schließen X
das Formular nicht verlassen werden kann solange die Daten
nicht stimmen:

:If bopen = True Then

DoCmd.CancelEvent
End If

Nun bekomme ich immer wenn Len(stMeldungA) > 0 eine Meldung
von Access: „Sie können diesen Datensatz momentan nicht
speichern. Möglicherweise ist … Möchten Sie das
Datenbankobjekt trotzdem schließen?“ Ja/Nein

Ich werde diese Meldung nicht los!

:Ich habe bereits versucht:

  • diverse Ereignisse abzubrechen (ich finde jedoch keines das
    diese Meldung generiert)
  • Sub Form_Error: If DataErr = 2169 Then Response =
    acDataErrContinue (Ich komme nicht auf Me!..SetFocus zurück
    ohne dass die eingegebenen Daten verschwinden)
  • DoCmd.SetWarnings False (Die Meldung erscheint trotzdem)

Ich möchte nicht eine extra Schaltfläche „Schließen“ anlegen
und das X ausblenden. Gibt es einen Weg die Meldung
loszuwerden/auszublenden und die Auswahl „Nein“ zu setzen?

Kann mir jemand helfen?

freilich

Viele Grüße vom Bodensee
Franz, DF6GL

Danke Franz für deine schnelle Antwort,

ich habe es gerade ausprobiert. Leider ohne Erfolg.
Hier mein Versuch:

Sub Form_BeforeUpdate(Cancel as Integer)

If (Fall a) Then
Me.Undo
Exit Sub
ElseIf (Fall b) then
Me!..SetFocus
Cancel = true
Exit Sub
Else: (Fall c)
End If

End Sub

Sub Form_Unload habe ich entfernt und auch die globale Variable bopen.

Die Cancel Eigenschaft des Form_BeforeUpdate-Ereignisses ist sicher die elegantere Lösung als das DoCmd.CancelEvent aber trotzdem bekomme ich wenn (Fall b) die Meldung von Access:
„Sie können diesen Datensatz momentan nicht speichern. Möglicherweise ist … Möchten Sie das Datenbankobjekt trotzdem schließen?“ Ja/Nein

Ja/Nein soll keine Option für den Anwender sein. Wenn ich das Form_BeforeUpdate-Ereignis abbreche, dann will ich damit auch gleichzeitig das Schließen-Ereignis abbrechen, d.h. ich will das automatisch „Nein“ ausgewählt ist.

Hast du noch einen weiteren Tip?

Liebe Grüße

Aiwala

Hallo,

vor dem ersten Exit Sub fehlt das Cancel =true

Poste mal den gesamten Code (mit Copy&amp:stuck_out_tongue_winking_eye:aste) und nicht nur solchen fragmetierten Teil, wo man das Meiste erahnen muss.

Bezgl. des Schließens kannst Du ja den vorherigen Code weiter benutzen.

Evtl. ist im Close_Ereignis ein
On Error goto next

erforderlich.

Viele Grüße vom Bodensee
Franz, DF6GL

Hallo Franz,
du bist ja superschnell!

Ich habe das mit dem Close-Ereigniss gerade ausprobiert. Bringt nichts! Die Meldung kommt immernoch.

vor dem ersten Exit Sub fehlt das Cancel =true

Der erste Teil funktioniert doch perfekt! Da fehlt kein Cancel = true

Poste mal den gesamten Code (mit Copy&amp:stuck_out_tongue_winking_eye:aste) und nicht nur
solchen fragmetierten Teil, wo man das Meiste erahnen muss.

Kann ich machen:

Private Sub Form_BeforeUpdate(Cancel As Integer)

On Error GoTo fehler

Dim ctl As Control
Dim stMeldungA As String
Dim stMeldungB As String
Dim iAntwortB As Integer
Dim db As DAO.Database
Dim rst As DAO.Recordset
Dim AnzahlDS As Single

For Each ctl In Me
If ctl.Properties(„ControlType“) = 111 Or ctl.Properties(„ControlType“) = 109 Then
If ctl.Tag = „x“ Then
If IsNull(ctl.Value) = True Then
stMeldungA = stMeldungA & ctl.Name & vbNewLine
End If
End If
End If
Next

For Each ctl In Me
If ctl.Properties(„ControlType“) = 111 Or ctl.Properties(„ControlType“) = 109 Then
If ctl.Tag = „y“ Then
If IsNull(ctl.Value) = True Then
stMeldungB = stMeldungB & ctl.Name & vbNewLine
End If
End If
End If
Next

If IsNull(Me!Seriennummer.Value) = True Then
Me.Undo
Exit Sub
ElseIf Len(stMeldungA) > 0 Then
If Len(stMeldungA) > 600 Then stMeldungA = Left(stMeldungA, 600) & vbNewLine & „etc.“
stMeldungA = „Folgende erforderliche Felder wurden nicht ausgefüllt:“ & vbNewLine & stMeldungA & vbNewLine & „Bitte tragen Sie die fehlenden Daten ein!“
MsgBox stMeldungA, vbOKOnly + vbCritical, „Warnmeldung“
Me!SAPNr.SetFocus
Cancel = True
Exit Sub
ElseIf Len(stMeldungB) > 0 Then
stMeldungB = „Folgende sinnvolle jedoch nicht erforderliche Felder wurden nicht ausgefüllt:“ & vbNewLine & vbNewLine & stMeldungB & vbNewLine & vbNewLine & „Wollen Sie noch Daten eintragen?“
iAntwortB = MsgBox(stMeldungB, vbYesNo + vbQuestion + vbDefaultButton1, „Warnmeldung“)
If iAntwortB = vbYes Then
Me!SAPNr.SetFocus
Cancel = True
Exit Sub
End If
End If

If Me!Vorgang.Value = „Wareneingang“ _
And Me!Grund.Value = „neu“ _
And Me![dieses Gerät wurde geliefert].Value = „von Lieferant“ _
And Len(Me![als Ersatz für das Gerät mit der Seriennummer].Value) > 0 _
Then
Set db = CurrentDb
Set rst = db.OpenRecordset(„Tabelle Historie“)

AnzahlDS = DCount(„Vorgangsnummer“, „Tabelle Historie“, „[Gerätetyp]=’“ & Me!Gerätetyp.Value & „’ AND [Seriennummer]=’“ & Me![als Ersatz für das Gerät mit der Seriennummer].Value & „’ AND [Vorgang]=‚Info Gerät ersetzt‘ AND [Grund]=‚Ausmustern‘“)
If AnzahlDS = 0 Then
rst.AddNew
rst.Fields(„Gerätetyp“).Value = Me!Gerätetyp.Value
rst.Fields(„Klassifizierung“).Value = Me!Klassifizierung.Value
rst.Fields(„Seriennummer“).Value = Me![als Ersatz für das Gerät mit der Seriennummer].Value
rst.Fields(„Vorgang“).Value = „Info Gerät ersetzt“
rst.Fields(„Datum des Vorgangs“).Value = Me![Datum des Vorgangs].Value
rst.Fields(„Grund“).Value = „Ausmustern“
rst.Fields(„Art des Geschäftspartners“).Value = „Lieferant“
rst.Fields(„laufende Nummer des Geschäftspartners“).Value = Me![laufende Nummer des Geschäftspartners].Value
rst.Fields(„dieses Gerät wurde geliefert“).Value = „von Lieferant ersetzt durch“
rst.Fields(„als Ersatz für das Gerät mit der Seriennummer“).Value = Me!Seriennummer.Value
If Len(Me!Schriftstück.Value) > 0 Then rst.Fields(„Schriftstück“).Value = Me!Schriftstück.Value
If Len(Me!Schriftstücknummer.Value) > 0 Then rst.Fields(„Schriftstücknummer“).Value = Me!Schriftstücknummer.Value
If Len(Me!Schriftstückdatum.Value) > 0 Then rst.Fields(„Schriftstückdatum“).Value = Me!Schriftstückdatum.Value
rst.Fields(„Ersteller bzw Prüfer“).Value = Me![Ersteller bzw Prüfer].Value
If Len(Me!Sonstiges.Value) > 0 Then rst.Fields(„Sonstiges“).Value = Me!Sonstiges.Value
rst.Update
rst.Close
End If

Set rst = Nothing
Set db = Nothing

MsgBox „Info Gerät ersetzt für SN " & Me![als Ersatz für das Gerät mit der Seriennummer] & " in ‚Tabelle Historie‘ geschrieben“

ElseIf Me!Vorgang.Value = „Warenausgang“ _
And Me!Grund.Value = „RTN“ _
And Me![dieses Gerät wurde geliefert].Value = „an Kunde“ _
And Len(Me![als Ersatz für das Gerät mit der Seriennummer].Value) > 0 _
Then
Set db = CurrentDb
Set rst = db.OpenRecordset(„Tabelle Historie“)

AnzahlDS = DCount(„Vorgangsnummer“, „Tabelle Historie“, „[Gerätetyp]=’“ & Me!Gerätetyp.Value & „’ AND [Seriennummer]=’“ & Me![als Ersatz für das Gerät mit der Seriennummer].Value & „’ AND [Vorgang]=‚Info Gerät ersetzt‘ AND [Grund]=‚RTN‘“)
If AnzahlDS = 0 Then
rst.AddNew
rst.Fields(„Gerätetyp“).Value = Me!Gerätetyp.Value
rst.Fields(„Klassifizierung“).Value = Me!Klassifizierung.Value
rst.Fields(„Seriennummer“).Value = Me![als Ersatz für das Gerät mit der Seriennummer].Value
rst.Fields(„Vorgang“).Value = „Info Gerät ersetzt“
rst.Fields(„Datum des Vorgangs“).Value = Me![Datum des Vorgangs].Value
rst.Fields(„Grund“).Value = „RTN“
rst.Fields(„Art des Geschäftspartners“).Value = „Kunde“
rst.Fields(„laufende Nummer des Geschäftspartners“).Value = Me![laufende Nummer des Geschäftspartners].Value
rst.Fields(„dieses Gerät wurde geliefert“).Value = „von Pico ersetzt durch“
rst.Fields(„als Ersatz für das Gerät mit der Seriennummer“).Value = Me!Seriennummer.Value
If Len(Me!Schriftstück.Value) > 0 Then rst.Fields(„Schriftstück“).Value = Me!Schriftstück.Value
If Len(Me!Schriftstücknummer.Value) > 0 Then rst.Fields(„Schriftstücknummer“).Value = Me!Schriftstücknummer.Value
If Len(Me!Schriftstückdatum.Value) > 0 Then rst.Fields(„Schriftstückdatum“).Value = Me!Schriftstückdatum.Value
rst.Fields(„Ersteller bzw Prüfer“).Value = Me![Ersteller bzw Prüfer].Value
If Len(Me!Sonstiges.Value) > 0 Then rst.Fields(„Sonstiges“).Value = Me!Sonstiges.Value
rst.Update
rst.Close
End If

Set rst = Nothing
Set db = Nothing

MsgBox „Info Gerät ersetzt für SN " & Me![als Ersatz für das Gerät mit der Seriennummer] & " in ‚Tabelle Historie‘ geschrieben“

End If

fehler:
If Err.Number = 0 Then
Cancel = True
ElseIf Err.Number = 2105 Then
MsgBox „Der erste/letzte Datensatz wurde bereits erreicht!“ & vbNewLine & „Weiter vor/hinter geht es nicht!“
Me!SAPNr.SetFocus
Cancel = True
Else
MsgBox „Es ist ein Fehler mit der Nummer " & Err.Number & " aufgetreten!“ & vbNewLine & "Wenden Sie sich bitte an den Datenbankersteller mit der Fehlernr und der Information: " & vbNewLine & "Fehler im ‚Sub Form_BeforeUpdate‘ im ‚Formular Warenwirtschaft alle‘ "
End If

End Sub

Private Sub Form_Close()
On Error Resume Next
End Sub

Ich hab es halt gekürzt, weil der ganze Programmtext etwas unübersichtlich ist.

Ich bin gespannt auf den nächsten Vorschlag :smile:

Hoffnungsvolle Grüße

Aiwala

Hallo,

wenn
If IsNull(Me!Seriennummer.Value) = True Then
Me.Undo
Exit Sub
.
.

eine Abbruchbedingung ist, dann fehlt Cancel =true …
.

Wozu wäre ansonsten Me.Undo sinnvoll?

„Nun bekomme ich immer wenn Len(stMeldungA) > 0 eine Meldung von Access: „Sie können diesen Datensatz momentan nicht speichern. Möglicherweise ist … Möchten Sie das Datenbankobjekt trotzdem schließen?“ Ja/Nein“

Diese Meldung kommt erst dann, wenn direkt nach einer Änderung am Datensatz das Form geschlossen werden soll. Durch das Schliessen-Ereignis wird versucht, den DS zu speichern, was wiederum das BeforeUpdate-Ereignis auslöst. Durch die Bedingung, bzw. den Abbruch des Ereignisses kommt Access in einen Konflikt.

Es ist in der Abbruchbedingung dann dafür zu sorgen, dass der Datensatz in einen vorherigen unbearbeiteten Zustand (Normalmodus, kein Editiermodus) versetzt wird, was durch mehrmalige(!) Me.Undo erreicht werden könnte(!).

Weiterhin ist Single als Datentyp für eine Ganzzahl („AnzahlDS“) fehl am Platz, wie auch Integer in Long geändert werden sollte.

Im Form_BeforeUpdate-Ereignis sollten keine Aktionen stattfinden, die nur nach erfolgreicher Speicherung des akt. DS sinnvoll sind. D. h. hier sollten NUR die Plausibilitäts-Checks erfolgen und Datenänderungen in anderen Tabellen („Tabelle Historie“) im Form_AFTERupdate-Ereignis geschehen.

(btw. Auf Leer- und Sonderzeichen in Objektnamen dringend verzichten!)

Viele Grüße vom Bodensee
Franz, DF6GL

Hallo Franz,

wenn
If IsNull(Me!Seriennummer.Value) = True Then
Me.Undo
Exit Sub
eine Abbruchbedingung ist, dann fehlt Cancel =true …
Wozu wäre ansonsten Me.Undo sinnvoll?

Dieser Teil hat die Aufgabe wenn die Seriennummer fehlt alle eingebenen Daten zu entfernen bzw. zu verhindern, dass der Datensatz gespeichert wird, aber trotzdem weitere Ereignisse wie Schließen oder Datensatzwechsel zuzulassen. => Es funktioniert!

„Nun bekomme ich immer wenn Len(stMeldungA) > 0 eine Meldung
von Access: „Sie können diesen Datensatz momentan nicht
speichern. Möglicherweise ist … Möchten Sie das
Datenbankobjekt trotzdem schließen?“ Ja/Nein“

Diese Meldung kommt erst dann, wenn direkt nach einer Änderung
am Datensatz das Form geschlossen werden soll. Durch das
Schliessen-Ereignis wird versucht, den DS zu speichern, was
wiederum das BeforeUpdate-Ereignis auslöst. Durch die
Bedingung, bzw. den Abbruch des Ereignisses kommt Access in
einen Konflikt.

Das ist ja das Problem! Ich versuche mit all dem zu erreichen, dass das Schließen-Ereignis nicht startet wenn im FormBeforeUpdate-Ereignis das Speichern verhindert wird.

Es ist in der Abbruchbedingung dann dafür zu sorgen, dass der
Datensatz in einen vorherigen unbearbeiteten Zustand
(Normalmodus, kein Editiermodus) versetzt wird, was durch
mehrmalige(!) Me.Undo erreicht werden könnte(!).

Mit Me.Undo sind aber die eingegebenen Daten weg! Der Anwender soll jedoch nicht nochmal von vorne anfangen müssen, sondern nur das fehlende ergänzen!

Weiterhin ist Single als Datentyp für eine Ganzzahl
(„AnzahlDS“) fehl am Platz, wie auch Integer in Long geändert
werden sollte.

AnzahlDS hat entweder den Wert O oder 1

Im Form_BeforeUpdate-Ereignis sollten keine Aktionen
stattfinden, die nur nach erfolgreicher Speicherung des akt.
DS sinnvoll sind. D. h. hier sollten NUR die
Plausibilitäts-Checks erfolgen und Datenänderungen in anderen
Tabellen („Tabelle Historie“) im Form_AFTERupdate-Ereignis
geschehen.

Ich habe deinen Rat befolgt und alle automatischen Datengeschreibsel in Form_AfterUpdate ausgelagert. Siehe unten!

(btw. Auf Leer- und Sonderzeichen in Objektnamen dringend
verzichten!)

Du hast recht! Das sind jedoch Altlasten und es wird eine erheblichen Aufwand kosten die Datenbank zu bereinigen. (Was du gefunden hast ist noch nicht alles *Seufz*

Hier die Neuerungen: (Die Meldung kommt immernoch)

Private Sub Form_BeforeUpdate(Cancel As Integer)

’ On Error GoTo fehler

Dim ctl As Control
Dim stMeldungA As String
Dim stMeldungB As String
Dim iAntwortB As Integer

For Each ctl In Me
If ctl.Properties(„ControlType“) = 111 Or ctl.Properties(„ControlType“) = 109 Then
If ctl.Tag = „x“ Then
If IsNull(ctl.Value) = True Then
stMeldungA = stMeldungA & ctl.Name & vbNewLine
End If
End If
End If
Next

For Each ctl In Me
If ctl.Properties(„ControlType“) = 111 Or ctl.Properties(„ControlType“) = 109 Then
If ctl.Tag = „y“ Then
If IsNull(ctl.Value) = True Then
stMeldungB = stMeldungB & ctl.Name & vbNewLine
End If
End If
End If
Next

If IsNull(Me!Seriennummer.Value) = True Then
Me.Undo
Exit Sub
ElseIf Len(stMeldungA) > 0 Then
If Len(stMeldungA) > 600 Then stMeldungA = Left(stMeldungA, 600) & vbNewLine & „etc.“
stMeldungA = „Folgende erforderliche Felder wurden nicht ausgefüllt:“ & vbNewLine & stMeldungA & vbNewLine & „Bitte tragen Sie die fehlenden Daten ein!“
MsgBox stMeldungA, vbOKOnly + vbCritical, „Warnmeldung“
Me!SAPNr.SetFocus
Cancel = True
Exit Sub
ElseIf Len(stMeldungB) > 0 Then
stMeldungB = „Folgende sinnvolle jedoch nicht erforderliche Felder wurden nicht ausgefüllt:“ & vbNewLine & vbNewLine & stMeldungB & vbNewLine & vbNewLine & „Wollen Sie noch Daten eintragen?“
iAntwortB = MsgBox(stMeldungB, vbYesNo + vbQuestion + vbDefaultButton1, „Warnmeldung“)
If iAntwortB = vbYes Then
Me!SAPNr.SetFocus
Cancel = True
Exit Sub
End If
End If

End Sub

Hallo,

tja, wenn das Close-Ereignis einmal „gefeuert“ hat, treten eben auch das BeforeUpdate und Afterupdate-Ereignis auf Wie beim DS-Wechsel). Zu diesem Zeitpunkt ist das Close-Ereignis nicht mehr zu stoppen…

Du kannst nicht Daten speichern wollen und gleichzeitig doch nicht…

Es wird wohl nichts anderes übrig bleiben, als eine Schaltfläche einzubauen, mit deren Ereigniscode erst geprüft wird , ob der DS nicht erst noch gespeichert werden muß. Wenn er „clean“ ist, dann darf das Form geschlossen werden. (If not Me.Dirty then Docmd.Close acForm, Me.Name)

Hallo,

gibt es denn keine Möglichkeit die Fehlermeldung mit „Nein“ über VBA-Code zu bestätigen? Manuell kann ich das anwählen. Wenn ich den Fehler über

Private Sub Form_Error(DataErr As Integer, Response As Integer)
If DataErr = 2169 Then Response = acDataErrContinue
End Sub

abfange ist automatisch „Ja“ ausgewählt. Gibt es eine Möglichkeit den Rückgabewert der Fehlermeldung zu setzen?

Liebe Grüße
Aiwala