Name der Prodzedur oder Funktion

Hallo,

weiss zufällig jemand wie man in VBA den Namen der Prozedur oder Funktion die gerade ausgeführt wird, auslesen kann.

Genauer gesagt geht es mir darum in der Routine zum Auffangen von Fehlern in VBA festzustellen, wo er genau entsteht. Am liebsten wäre mir natürlich der Modulname und der Prozedurname.

Danke & LG, Florian.

Tja,
warum lässt Du den Code nicht schrittweise durchlaufen, indem Du den Editor öffnest, den Kursor in die gewünschte Prozedur setzt, und nun die F8 Taste solange drückst, bis das Programm stoppt. Dann weisst Du genau, wo Du bist.

Oder Du kannst follgenden Aufruf machen:
Er gibt aber nur das Modul, nicht aber die Prozedure an.

Dim a
a = Application.VBE.ActiveCodePane.CodeModule 'Aktives Codemodul

MFG Sebastian

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

Hallo,

wir geben entsprechendes derart an:

'---Fehlerbehandlungsblock----------------------------------------
HandleErr:
 Select Case Err.Number
 Case Else
 MsgBox "Fehler " & Err.Number & ": " & Err.Description, \_ 
 vbCritical, "mod\_formModule.fctAnbieterZeigen" 
 End Select
'---Ende des Fehlerbehandlungsblocks.-----------------------------

Gruß
D. Scholdei

Hallo, Florian!

Ergänzend zu Daniels Fehlerabfangblock, den ich in ähnlicher Form ebenfalls verwende: Zusätzlich kommt eine modulweite Konstante für den Modulnamen hinzu bzw. statt „mod_formModule“, ein mal im allgemeinen Teil deklariert, und dann in der Abfangroutine ebenfalls angezeigt.

Diesen so eigentlich immer gleichen Prozedurrumpf kopiere ich mir in JEDE Routine, selbst wenn ich weiß, dass eigentlich kein Fehler auftreten kann. Aber es gibt ja den Spruch mit den Pferden vor Apotheken und so. Dann nur kurz ebenfalls per Copy & Paste den Prozedurnamen geändert, et voilà. Ein mal einfügen aus Notepad, ein mal kopieren des Prozedurnamens und diesen ein mal eingefügt: in ca. 3 bis 5 Sekunden ist alles erledigt.

Gruß, Manfred

Hallo @,

Danke für die Antworten. Ganz ist das leider noch nicht das was ich suche …

warum lässt Du den Code nicht schrittweise durchlaufen, indem
Du den Editor öffnest, den Kursor in die gewünschte Prozedur
setzt, und nun die F8 Taste solange drückst, bis das Programm
stoppt. Dann weisst Du genau, wo Du bist.

Direkt die Prozedur ablaufen lassen will ich nicht, da ich generell Fehlermeldungen eher zu unterdrücken versuche oder gleich im Code behandele, damit Leute die sich nicht so gut damit auskennen trotzdem mit der DB arbeiten können.

Ich lasse mir immer die Fehler-Nummer und Fehlerbeschreibung ins Direktfenster schreiben und sehe erst etwas später wenn etwas passiert. Oft sind ja Fehler nicht wirklich schlimm, verwirren die Leute aber trotzdem … hier wäre es aber auch angenehm den genauen Ort (Prodzedur, Modul, … je genau desto besser) wo der Fehler entsteht dazu geliefert zu bekommen.

(und um jeglichen Kommentaren entgegenzuwirken … ja ich teste meine Sachen schon vorher und in der Regel funktionieren sie auch :smile:

Dim a
a = Application.VBE.ActiveCodePane.CodeModule 'Aktives Codemodul

Das wäre mal ein Anfang um das ganze einzugrenzen. Probiere ich natürlich sofort aus :smile:

Was ich vermeiden will, dass ich jedes Mal den Code irgendwie anpassen muss um den Ort des Fehlers mitzubekommen. Nachdem, wenn es sich nicht um eine Fehlernummer handelt, die ich direkt abfrage, ich die Fehlerprozedur überhaupt in eine Sub-Prozedur wäre das beste wenn ich ähnlich wie bei Formularen mit „Me.Name“ den Namen direkt übergeben könnte …

Nochmals Danke & LG, Florian.

Hallo, Florian!

Direkt die Prozedur ablaufen lassen will ich nicht, da ich
generell Fehlermeldungen eher zu unterdrücken versuche oder
gleich im Code behandele, damit Leute die sich nicht so gut
damit auskennen trotzdem mit der DB arbeiten können.

Der Gedanke ist schon einmal der richtige. Ich mache das so:

  1. Ich habe eine Fehlerlogging-Klasse, der man verschiedene Output-Parameter mitgeben kann (das mache ich nur ein mal initial): Ausgabe der Fehler in Datei, in eine Tabelle und per MessageBox.

  2. In JEDE Prozedur bastel ich einen Prozedurrumpf rein, der bei mir direkt so aussieht:

    Sub Wonneblubber()
    '**
    '===============================================================================
    ’ Beschreibung:
    ’ In:
    ’ Out:
    ’ Global:
    ’ Angelegt: 01.01.2004 / MT
    ’ Änderung: 01.01.2004 / MT
    '===============================================================================
    '/**
    Const cstrProcName = „Wonneblubber“ 'ErrorHandler:blush:$N=FindFiles
    '--------------------
    On Error GoTo ErrorHandler

    ’ Fehlerbehandlungsblock hinzugefügt vom Fehlerbehandlungsroutinen-Add-In. Bearbeiten Sie diesen Codeabschnitt NICHT.
    '--------------------
    ErrorHandler:
    Select Case Err.Number
    Case 0
    Case Else
    logObj.logError mcstrModName, cstrProcName, Err.Number, Err.Description, Err.Source
    Resume ErrorHandler
    End Select
    ’ Ende des Fehlerbehandlungsblocks.
    End Sub

  3. Das obige logObj ist eine globale Instanz meiner Logging-Klasse. Nach dem Einfügen des Rumpfes muss ich nur mit Doppelklick, Kopieren, Doppelklick, Einfügen den Prozedurnamen der Konstanten cstrProcName mitgeben, den Modulnamen mcstrModName lege ich ein Mal modulweit fest.

  4. Alle zu behandelnden bzw. besser: behandelbaren, weil vorhersehbaren Fehler fange ich in der Routine ab, z. B. wenn beim Löschen eines Objekts dieses nicht vorhanden ist (der gewünschte Effekt also eintritt) mit einem

    Case
    Resume Next

  5. Treten Fehler auf, kommt es im schlimmsten Fall zu einer mit „Ok“ zu quittierenden Fehlermeldung, die der Anwender per Screenshot an mich schicken kann. In regelmäßigen Abständen könnte ich mir auch die Protokolldatei/-tabelle schicken lassen, um die Fehler zu lokalisieren.

Ich lasse mir immer die Fehler-Nummer und Fehlerbeschreibung
ins Direktfenster schreiben und sehe erst etwas später wenn
etwas passiert.

Das ist aber schon mal ganz schnell weg. Sitzt Du beim Programmlauf daneben? Dann geht das ja. Falls nicht, solltest Du Dir eine etwas dauerhaftere Art der Fehlerprotokollierung ausdenken.

Oft sind ja Fehler nicht wirklich schlimm,
verwirren die Leute aber trotzdem … hier wäre es aber auch
angenehm den genauen Ort (Prodzedur, Modul, … je genau desto
besser) wo der Fehler entsteht dazu geliefert zu bekommen.

Genau das tut die Logging-Klasse, wenn die Fehlerabfangroutine in jeder Funktion ist. Die Source-Eigenschaft des Error-Objekts ist nicht immer ganz zuverlässig, wenn ein globales Abfangen definiert wurde, in den nachfolgend/verschachtelt aufgerufenen Funktionen aber nicht: Du bekommst die initiale Routine, nicht aber diejenige, in der wirklich der Fehler produziert wurde.

(und um jeglichen Kommentaren entgegenzuwirken … ja ich
teste meine Sachen schon vorher und in der Regel funktionieren
sie auch :smile:

Alles kann man gar nicht testen („Hello World!“ vielleicht mal ausgenommen). Und bestimmte Fehler sind, wie Du selbst schrubtest, völlig egal bzw. können sogar gezielt provoziert werden, um bestimmte Kriterien zu überprüfen (z. B. Auslesen einer Eigenschaft eines nicht existenten Objekts, um eben dessen Existenz zu überprüfen: Fehlerfall hieße: Objekt gibt’s nicht.) Also mal keine Sorgen.

Was ich vermeiden will, dass ich jedes Mal den Code irgendwie
anpassen muss um den Ort des Fehlers mitzubekommen. Nachdem,

Das würde ich aber machen. Ist einmalig ein blöder Aufwand, aber beim weiteren Entwickeln ein nicht signifikanter Mehraufwand.

wenn es sich nicht um eine Fehlernummer handelt, die ich
direkt abfrage, ich die Fehlerprozedur überhaupt in eine

Bei den vorhergesehenen Fehlern wird die Logging-Klasse nicht aufgerufen (s. Beispiel oben mit zusätzlichem Case-Konstrukt). Hier ist die Bedeutung „Fehler“ also wirklich als „unvorhergesehener Fehler“ zu verstehen. Normal abgefangene und behandelte Fehler sind auch keine Fehler in dem Sinne, dass der Programmfluss so gestört wird, dass unerwünschte/falsche Ergebnisse geliefert werden.

Sub-Prozedur wäre das beste wenn ich ähnlich wie bei
Formularen mit „Me.Name“ den Namen direkt übergeben könnte …

Das würde mit dem Festlegen der mcstrModName in meinem obigen Beispiel geschehen. Und in Formularen schreibe ich hier in der Tat als Erstes beim Laden: mcstrModName = Me.Name

Gruß, Manfred

2 Like