Neuigkeiten:

Ist euer Problem gelöst, dann bitte den Knopf "Thema gelöst" drücken!

Mobiles Hauptmenü

weiter-button nur zulassen, wenn [ID] nicht neu ist

Begonnen von Carl, März 10, 2018, 21:13:08

⏪ vorheriges - nächstes ⏩

Carl

Ich möchte aus einem Formular heraus ein weiteres Formular öffnen und dabei die ID übergeben, das funktioniert auch:


Private Sub weiter_Click()
DoCmd.Save acForm, "frmTNanlegen"
DoCmd.OpenForm "frmFrage000"
   Forms!frmFrage000.Recordset.FindFirst "ID = " & Nz(Me!ID, 0)
End Sub


Dieses Problem besteht darin, dass, wenn nicht alle 4 Felder im Ursprungsformular ausgefüllt sind, die ID noch auf [NEU] ist und keine ID besteht. In diesem Fall wird im zu öffnenden Formular die ID "1" aufgerufen. Und das, obwohl ich vorher speichern lasse.

Wie kann ich es machen, dass vor der Prozedur der Datensatz angelegt wird und eine ID erhält?

Carl

PhilS

DoCmd.Save speichert das Design des Formulars, nicht den aktuellen Datensatz. Verwende Me.Dirty = False stattdessen.
Neue Videoserie: Windows API in VBA

Klassische CommandBars visuell bearbeiten: Access DevTools CommandBar Editor

Carl

Wie statt dessen? Me.Dirty = False soll wo hinein?

Carl

Lachtaube

Stattdessen bedeutet Ersatz für das zuvor Erwähnte oder anstelle des zuvor Genannten.
Grüße von der (⌒▽⌒)

Beaker s.a.

Alles, was geschieht, geschieht. - Alles, was während seines Geschehens etwas anderes geschehen lässt, lässt etwas anderes geschehen. - Alles, was sich selbst im Zuge seines Geschehens erneut geschehen lässt, geschieht erneut. - Allerdings tut es das nicht unbedingt in chronologischer Reihenfolge.
(Douglas Adams, Mostly Harmless)

Carl

Ich habe jetzt alles in allen möglichen Kombinationen ausprobiert und es treten neue unerwünschte Effekte auf. Ich hab jetzt ne andere Idee. Das komplette Problem lässt sich umgehen, wenn der Button "weiter" nur aktiv ist, wenn die Felder [feld1] bis [feld4] ausgefüllt wurden, also nicht null sind.

Ich habe jetzt mal versucht, den Button unsichtbar zu machen


Private Sub Form_Current()
If IsNull(Me!textfeld1) Then
         Me!weiter.Visible = False
       Else
         Me!weiter.Visible = True
     End If
End Sub


aber hier kommt es beim Laden und beim Aktualisieren zu unerwünschten Nebeneffekten. Von daher die Frage:

Gibt es einen Code, der beim Klicken des Buttons weiter kontrolliert, ob Felder 1-4 nicht null sind und wenn eines null ist, eine msgbox ausgibt und wenn keines null ist, normal speichert und die ID übergibt und weiter macht?

Carl

PhilS

Zitat von: Carl am März 15, 2018, 07:39:39Gibt es einen Code, der beim Klicken des Buttons weiter kontrolliert, ob Felder 1-4 nicht null sind und wenn eines null ist, eine msgbox ausgibt und wenn keines null ist, normal speichert und die ID übergibt und weiter macht?
Klar.
Du hast ja die Kern-Logik für ein Feld in deinem Beispiel schon umgesetzt. Die Erweiterung auf 4 Felder ist jetzt eigentlich eine reine Fleiß-Übung.
Neue Videoserie: Windows API in VBA

Klassische CommandBars visuell bearbeiten: Access DevTools CommandBar Editor

MzKlMu

#7
Hallo,
Du solltest das Verlassen des Formulars wenn nicht alle Felder ausgefüllt sind erst gar nicht zulassen.
Daher ist zunächst mal das Ereignis "Beim Anzeigen" nicht geeignet. Es wird ein Ereignis benötigt das sich abbrechen lässt. Da nimmt man vor Aktualisierung. Das sieht dann so aus:
Private Sub Form_BeforeUpdate(Cancel As Integer)
Dim Pruefung As Integer
    Pruefung = IsNull(Me.Feld1) + IsNull(Me.Feld2) + IsNull(Me.Feld3) + IsNull(Me.Feld4)
    If Pruefung = 0 Then
      'alles OK, Weiter freischalten
      Me.weiter.Visible = True
    Else
      MsgBox "Es ist nicht alles ausgefüllt"
      Cancel = True 'speichern abbrechen
    End If
End Sub

Erläuterung:
IsNull(Feld) liefert einen Wahrheitswert (-1 bei zutreffend, 0 bei nicht zutreffend. Steht was im Feld ist Null nicht zutreffend also wird 0 zurückgegeben.
Die Addition ergibt einen Wert zwischen 0 und -4. Bei 0 ist alles klar, bei <> 0 fehlt ein Feld.
Im Ereignis "Beim Anzeigen"
sollte man den Weiter Button immer zuerst unsichtbar schalten.
Private Sub Form_Current()
         Me.weiter.Visible = False
End Sub

Im Grunde kannst Du Dir den Weiter Button einfach sparen, oder immer sichtbar lassen, denn mit meinem Vorschlag kommst Du ohnehin nur weiter wenn alle Felder ausgefüllt sind. Und es gibt ja eine Meldung, wenn nicht alle Felder gefüllt sind.

Mit etwas mehr Aufwand lässt sich das Ganze so ausbauen, dass man noch nicht mal die DB beenden kann ohne Prüfung.
Entsprechendes Beispiel mal im Anhang.
Gruß Klaus

Carl

Das ist ne gute Datei, da kann man viele Ideen finden. Danke.

Mal ne Frage, ich hab's so umgesetzt und es funktioniert!!Aber wenn ich einen speichernn-button klicke, wenn nicht alle Felder ausgefüllt sind, kommt nach der msgbox ("bitte alle felder ausfüllen") noch zusätzlich eine Fehlermeldung "3021" und er fordert zum debuggen auf.

Hier der button, der die Fehlermeldung 3021 verursacht.


Private Sub speichernn_Click()
DoCmd.Save acForm, "frmTNanlegen"
Me.Refresh
End Sub


Me.Refresh soll hier bewirken:

(i) dass der Button "weiter" überhaupt sichtbar wird, der auf die nächste Seite führt und die ID übergibt
(ii) dass aber zuvor ein Kennzeichen berechnet und angezeigt wird, das der Anwender sehen soll und das hier aber nicht wichtig für das Problem ist. Jedenfalls benötige ich zum verlassen zwei Buttons.

Wie werde ich 3021 los?

Carl

Lachtaube


Private Sub speichernn_Click()
   If Me.Dirty Then Me.Dirty = False
   'oder auch
   If Me.Dirty Then RunCommand acCmdSaveRecord
End Sub
... und in Form_BeforeUpdate prüfst Du die Felder auf Gültigkeit und setzt bei Ungültigkeit Cancel = True, womit der Datensatz weiterhin Dirty bleibt. Durch Drücken der Esc-Taste oder durch Absetzen der Anweisung Me.Undo kannst Du auch alle Änderungen am Datensatz rückgängig machen.

Allgemeine Fehler, wie z. Bsp. Verletzung von Gültigkeitsregeln, falsche Datentypen im Steuerelement, etc. kann man in Form_Error behandeln oder im speziellen in Steuerelementname_BeforeUpdate.
Grüße von der (⌒▽⌒)

MzKlMu

Hallo,
DoCmd.Save acForm, "frmTNanlegen"Wie oft muss man denn Dir das noch sagen ?
Die Codezeile speichert keine Daten. Damit wird ein ggf. geänderte Entwurf gespeichert, sonst nix.
Den Fehler 3021 musst Du mit einer Fehlerbehandlung abbrechen.
Aber wie gesagt, Dein Button speichert nix. Und das Me.Refresh darf an der Stelle auch bezweifelt werden.

Zitat von: Lachtaubeund in Form_BeforeUpdate prüfst Du die Felder auf Gültigkeit und setzt bei Ungültigkeit Cancel = True,
Steht schon genau beschrieben hier in #7 in diesem Thema mit Codebeispiel.
Gruß Klaus

Carl

Ja, okay, ich habs jetzt kapiert. Ich habe in der Tabelle nachgesehen, der DS wird wirklich nicht gespeichert.

Dirty ist auf true wenn er unvollständig ist. Aber der Fehler 3021 kommt auch bei der Lösung von Lachtaube unverändert und ich kann das Formular nur durch Debuggen verlassen. (Alles andere geht.)

Wieso wird der Datensatz noch immer nicht angelegt?

Carl

Lachtaube

Mein VBA-Direktfenster sagt mir:
?AccessError(3021)
Kein aktueller Datensatz.

Ohne Kenntnisse des verwendeten Codes kann ich damit wenig anfangen.
Grüße von der (⌒▽⌒)

Carl

Also hier ist der gesamte Code der Seite. Er speichert den Datensatz nicht und dadurch kommt 3021 beim refresh oder beim verlassen.


Option Compare Database
Option Explicit

Private Sub Form_Current()
         'DoCmd.SetWarnings = False
         Me.weiter.Visible = False
End Sub

'hier wird ein wert eingegeben
Private Sub vpnAnagramMother_Dirty(Cancel As Integer)
If Me.Dirty Then RunCommand acCmdSaveRecord
Me.Refresh
End Sub

Private Sub vpnWord_KeyPress(KeyAscii As Integer)
     Select Case KeyAscii
       Case 65 To 122, 8
       Case 13
        Me.weiter.SetFocus
       Case Else
         KeyAscii = 0
     End Select
End Sub

Private Sub vpnWord_Exit(Cancel As Integer)
If Me.Dirty Then RunCommand acCmdSaveRecord
Me.Refresh
End Sub

Private Sub vpnbirthdaySelfYear_KeyPress(KeyAscii As Integer)
     Select Case KeyAscii
       Case 48 To 57, 8
       Case 13
         Me.vpnWord.SetFocus
       Case Else
         KeyAscii = 0
     End Select
End Sub

Private Sub vpnbirthdaySelfYear_Exit(Cancel As Integer)
If Me.Dirty Then RunCommand acCmdSaveRecord
Me.Refresh
End Sub

Private Sub Form_BeforeUpdate(Cancel As Integer)
Dim Pruefung As Integer
    Pruefung = IsNull(Me.vpnAnagramMother) + IsNull(Me.vpnEyecolor) + IsNull(Me.vpnbirthdaySelfYear) + IsNull(Me.vpnWord)
    If Pruefung = 0 Then
      'alles OK, Weiter freischalten
      Me.weiter.Visible = True
    Else
      MsgBox "Bitte alle Felder ausfüllen!"
      Cancel = True 'speichern abbrechen
    End If
End Sub

'button, nach dessen Klicken das Kennzeichen aus den Feldern berechnet und engezeigt wird.
Private Sub kennzeichenanzeigen_Click()
   'If Me.Dirty Then Me.Dirty = False
   'oder auch
   If Me.Dirty Then RunCommand acCmdSaveRecord
   Me.Refresh
End Sub

Private Sub weiter_Click()
DoCmd.OpenForm "frmFrage000", , , "ID = " & Me.ID
DoCmd.Close acForm, "frmTNanlegen", acSaveYes
End Sub


Was könnte noch falsch sein?

Carl

Lachtaube

Weniger Code kann manchmal mehr sein.
Option Compare Database
Option Explicit

Private Sub Form_Current()
   'DoCmd.SetWarnings = False
   'Me.weiter.Visible = Not Me.newreord
End Sub

'hier wird ein wert eingegeben
Private Sub vpnAnagramMother_Dirty(Cancel As Integer)
   'If Me.Dirty Then RunCommand acCmdSaveRecord
   'Me.Refresh
End Sub

Private Sub vpnWord_KeyPress(KeyAscii As Integer)
   Select Case KeyAscii
      Case 65 To 122, 8
      Case 13
         Me.weiter.SetFocus
      Case Else
         KeyAscii = 0
   End Select
End Sub

Private Sub vpnWord_Exit(Cancel As Integer)
   'If Me.Dirty Then RunCommand acCmdSaveRecord
   'Me.Refresh
End Sub

Private Sub vpnbirthdaySelfYear_KeyPress(KeyAscii As Integer)
   Select Case KeyAscii
      Case 48 To 57, 8
      Case 13
         Me.vpnWord.SetFocus
      Case Else
         KeyAscii = 0
   End Select
End Sub

Private Sub vpnbirthdaySelfYear_Exit(Cancel As Integer)
   'If Me.Dirty Then RunCommand acCmdSaveRecord
   'Me.Refresh
End Sub

Private Sub Form_AfterUpdate()
   'alles OK, Weiter freischalten
   'Me.weiter.Visible = True
End Sub

Private Sub Form_BeforeUpdate(Cancel As Integer)
   Dim Pruefung As Integer

   Pruefung = IsNull(Me.vpnAnagramMother) + _
              IsNull(Me.vpnEyecolor) + _
              IsNull(Me.vpnbirthdaySelfYear) + _
              IsNull(Me.vpnWord)
   If Pruefung < 0 Then
      MsgBox "Bitte alle Felder ausfüllen!"
      Cancel = True   'speichern abbrechen
   End If
End Sub

'button, nach dessen Klicken das Kennzeichen aus den Feldern berechnet und engezeigt wird.
Private Sub kennzeichenanzeigen_Click()
   'If Me.Dirty Then Me.Dirty = False
   'oder auch
   'If Me.Dirty Then RunCommand acCmdSaveRecord
   'Me.Refresh
End Sub

Private Sub weiter_Click()
   If Me.Dirty Then Me.Dirty = False
   If Me.NewRecord Then Exit Sub
   
   DoCmd.OpenForm "frmFrage000", , , "ID = " & Me.ID
   DoCmd.Close acForm, "frmTNanlegen", acSaveYes
End Sub
Grüße von der (⌒▽⌒)