Neuigkeiten:

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

Mobiles Hauptmenü

Wann stirbt die „Sprungmarke” Next?

Begonnen von Doming, Juli 14, 2025, 13:29:39

⏪ vorheriges - nächstes ⏩

Doming

Hallo,

Private Sub blah()
On Error GoTo Fehler
    ....
Fehler:
    Fehlermeldung Err.Number, Err.Description
    Resume Next
End Sub

Private Sub Fehlermeldung(FCode, FText As String)
    MsgBox "Ein Fehler mit dem Code " & FCode & " wurde festgestellt" & vbCrLf _
         & "Die Beschreibung dazu lautet: " & FText
End Sub

Wann verliert der Errorhandler die Zeile, welche einen Fehler auslöste? Sobald ich Err.Clear aufrufe?
Oder wenn ich durch mehrere Prozeduren springe?

Gruß
 Doming

Bitsqueezer

Hallo,

der Handler kann nur in der Prozedur, in der er ist, den Fehler behandeln.

Wenn es keinen gibt, ist die aufrufende Zeile in der übergeordneten Prozedur der Fehlerauslöser dort, auch wenn der Fehler innerhalb der aufrufenden Prozedur stattfand. Wenn es dort einen Fehlerhandler gibt, wird dieser angesprungen. Wenn nicht, den nächst höheren Aufrufer, und wenn es keinen mehr gibt, springt der Access-Debugger an.

Err.Clear hebt natürlich jeden Fehler auf.
Resume in allen Varianten auch.

Eine Fehlerzeile kann nur verwendet werden, wenn man auch Zeilennummern verwendet, das sollte man aber heutzutage nicht mehr machen, ist auch völlig unnötig.

Ich mache das so, daß ich Errorhandler immer mit MZTools einfüge, was den Vorgang stark vereinfacht.
Dazu hänge ich an den Errorhandler unten nach der letzten Zeile eine Zeile "Resume" an. Diese wird also nie ausgeführt.
Wenn ich den Fehler untersuchen will und im Fehlerhandler stoppe, kann ich dann den Programmzähler auf "Resume" springen lassen und diesen ausführen, dann springt er mir auf genau die Zeile, die den Fehler verursacht hat - ganz ohne Zeilennummern.

Gruß

Christian


Knobbi38

Hallo,

im Prinzip stimmt das schon, was Christian da mit den Errorhandlern beschrieben hat, nur
Zitat von: Bitsqueezer am Juli 14, 2025, 13:52:35Err.Clear hebt natürlich jeden Fehler auf.
Err.Clear löscht nur das Error-Objekt, setzt aber nicht den Errorhandler zurück! Err.Clear wird implizit auch bei
  • Allen Arten von Resume-Anweisungen
  • Exit Sub, Exit Function, Exit Property
  • Einer On Error -Anweisung
aufgerufen.

Hier mal ein paar weiter führende Links:
https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-basic-6/aa716196(v=vs.60)
http://www.cpearson.com/excel/errorhandling.htm
https://stackoverflow.com/questions/14158901/difference-between-on-error-goto-0-and-on-error-goto-1-vba

Gruß Knobbi38

Doming

Danke für die Ausführungen.
Mein aktuelles Problem ist folgendes: Offenbar ist letzte Nacht kein Datenexport aus SAP erfolgt, eine von mir genutzte Nachschlagetabelle funktioniert also nicht. Ein gute Gelegenheit, eine Ausnahme im Errorhandler einzubauen.
Public Function TabelleOK(Tabelle As String) As Boolean
On Error GoTo Fehler
 Dim Menge
    Menge = DCount("*", Tabelle)
    TabelleOK = True
Ende:
    Err.Clear
    Exit Function
Fehler:
    Resume Ende
End Function

Mit dieser Funktion setze ich eine lokale Variable
    On Error Goto Fehler 
    BooltblOK = TabelleOK("tblSAPDaten")
    If BooltblOK then
        Eingabe "Importiere Daten aus SAP"
        SAPLesen
    Else
        Eingabe "Tabelle tblSAPDaten ist nicht lesbar"
    End if
    ...
    Exit Sub
Fehler:
    Eingabe "Fehler (" & Err.Number & ") Prozedur Ablauf:" & Err.Description
    Resume Next
End Sub
'Eingabe' gibt dem Nutzer die aktuelle Aktion aus
Public Sub Eingabe(Txt As String)
    Debug.Print Err.Number
    CurrentDb.Execute "INSERT INTO tbl_WartungsProtokoll(Zeit, Tat) VALUES (" _
                     & fncTimSQL(Now) & ", '" _
                     & Txt & "')"
Das hat jetzt folgenden Effekt:
tblSAPDaten ist nicht vorhanden, also booltblOK ist False und die Meldung "nicht lesbar" wird ausgegeben.
Dann wird erneute eine Eingabe generiert, mit dem Fehler 3075 Tabelle nicht vorhanden, obwohl mit Err.Number vorher mit 0 angezeigt wird. Eigentlich war der Fehler doch schon abgefrühstückt?

Knobbi38

Hallo,

mehrere Errorhandler machen eine Sache nicht sicherer! Wenn du Errorhandler in TabelleOK() und SAPLesen() hast, was ja richtig ist, dann kannst du dir in der aufrufenden Sub den Errorhandler sparen, weil dort eigentlich der Rückgabewert ausgewertet werden sollte. Die Variable "BooltblOK" ist deshalb auch nicht notwendig.

Der Programmablauf sollte also nochmal etwas überarbeitet werden, SAPLesen() einen Rückgabewert liefern und den Errorhandler in der übergeordneten Sub entfernen. Du kannst dir den PAP ja mal als Nassi-Shneiderman Diagramm auf Papier kurz skizzieren, oft hilft das.

Gruß Knobbi38

PS:
Was genau möchtest du eigentlich mit TabelleOK() überprüfen?


PhilS

Zitat von: Doming am Juli 14, 2025, 15:05:24tblSAPDaten ist nicht vorhanden, also booltblOK ist False und die Meldung "nicht lesbar" wird ausgegeben.

Dann wird erneute eine Eingabe generiert, mit dem Fehler 3075 Tabelle nicht vorhanden, obwohl mit Err.Number vorher mit 0 angezeigt wird.
Dann schau dir mal genau an was in deinem hier nicht gezeigtem Code-Segment "..." passiert. M.M. muss dort erneut auf die nicht vorhandene SAP-Tabelle zugegriffen werden und dabei wird der neue Fehler ausgelöst.
Neue Videoserie: Windows API in VBA

Klassische CommandBars visuell bearbeiten: Access DevTools CommandBar Editor

Doming

Die lokale, boolsche Variable setze ich, weil ich im Nachgang noch mehrere Datensätze aus der Tabelle nutzen möchte, dazu muss nicht jedes Mal erneut das DCount losgeschickt werden.

Das ganze Resume Next ist mir eigentlich zuwider, aber der ganze Rotz soll im Hintergrund ablaufen. Wenn Fehler auftreten sollen sie ins Protokoll, ansonsten möchte ich da keine Unterbrechungen bei den Anwendern.

Morgen kann ich wieder weiter rumprobieren...

PhilS

Zitat von: Doming am Juli 14, 2025, 21:06:18Das ganze Resume Next ist mir eigentlich zuwider, aber der ganze Rotz soll im Hintergrund ablaufen. Wenn Fehler auftreten sollen sie ins Protokoll, ansonsten möchte ich da keine Unterbrechungen bei den Anwendern.
Ich zweifle ob auch dafür dein Ansatz mit Resume Next so geeignet ist. 
Wenn in einem mehrstufigen Ablauf Fehler auftreten, erscheint es fragwürdig, ob es Sinn macht den Prozess fortzusetzen, wenn bereits Fehler aufgetreten sind. 
Neue Videoserie: Windows API in VBA

Klassische CommandBars visuell bearbeiten: Access DevTools CommandBar Editor

Knobbi38

Zitat von: Doming am Juli 14, 2025, 21:06:18Die lokale, boolsche Variable setze ich, weil ich im Nachgang noch mehrere Datensätze aus der Tabelle nutzen möchte, dazu muss nicht jedes Mal erneut das DCount losgeschickt werden.
Wieso sollte man mehrmals DCount() aufrufen müssen? Alles gehört in einen IF THEN ELSE Zweig:
IF TabelleOK() then
  ' Todo:
ELSE
  ' Error:
END IF

Vielleicht kannst du mal deinen ganzen Code hier zeigen, sonst wird eine Hilfe schwierig.

Knobbi38


Doming

#9
Hallo,

um die Geschichte mal etwas aufzuklären:
Ich habe hier ein paar alte Datenbanken, deren Daten aufeinander aufbauen. Der damalige Autor hat sich nicht unbedingt an die Normalisierung gehalten, d.h. er hat je nach Nutzung diverse Tabellen, die parallele Daten enthalten.

Wenn der Nutzer "sein" Formular startet, werden Abfragen gestartet die dann die gewünschten Daten aufbereitet und in eine neue Tabelle schreibt.

Ich versuche, bei einer nachgeschalteten Datenbank die Abläufe umzubauen. Leider kann ich das nur, wenn die vorherigen DB die richtigen Daten liefern. Also habe ich das, was die diversen Nutzer beim Starten ihrer Formulare bewirken, in eine SchattenDb ausgelagert. Diese DB wiederum wird immer von demjenigen gestartet, der am Tag als Erster mit den Daten zu tun hat. So kommen am Ende die Tabellen raus, die ich bei meinem eigentlichen Projekt brauche.

Deswegen auch die Tabelle mit den aktuellen Nutzern im Parallelthread damit die SchattenDB nicht mehrmals gestartet wird und sich bei Nichtgebrauch wieder abschaltet.

Natürlich wäre es am besten, wenn man den ganzen DB-Wald mal komplett durchforstet und neu aufsetzt, um die gewachsenen Strukturen zu durchbrechen, aber solange die alten Dinge ,,irgendwie" laufen, nimmt keiner Geld in die Hand, um etwas neu zu bauen. Ich bin ja froh, dass man mich machen lässt, auch wenn ich keiner IT-Abteilung angehöre.

Achja, worum es mir bei der lokalen BoolVariable ging: Ich nehme immer mehr Zwischenaktionen in die SchattenDB auf, die dann auch auf die SAP-Daten zugreifen. Das kann dann auch mal im Ablauf etwas später sein. Wenn ich später dazu komme, kann ich den Ablauf auch nochmal durcharbeiten und optimieren. Erstmal soll es laufen, also die Pflicht vor der Kür ;-)

Gruß
Doming

Knobbi38

Hallo Doming,

Zitat von: Doming am Juli 16, 2025, 08:50:25Achja, worum es mir bei der lokalen BoolVariable ging: Ich nehme immer mehr Zwischenaktionen in die SchattenDB auf, die dann auch auf die SAP-Daten zugreifen. Das kann dann auch mal im Ablauf etwas später sein. Wenn ich später dazu komme, kann ich den Ablauf auch nochmal durcharbeiten und optimieren.

ich weiß nicht, ob das die richtige Vorgehensweise ist, denn eine einfache Variable ist nicht persistent und um den Fortschritt der Verarbeitung zu speichern, sollte diese persistent festgehalten werden, damit ein "Restart" jederzeit möglich ist.

Gruß Knobbi38