Die Inventor FAQ wird unterstützt von:

Inventor FAQ Logo

20.02.2017

Inventor automatisieren: Programmieren für Konstrukteure (Teil 7)

Teil 6 verpasst? Dann erstmal hier weiter!

Alle Beiträge der Serie

In Teil 6 haben wir ein Programm geschrieben, dass Skizzen in Bauteilen  (un-)sichtbar geschaltet hat. Dabei sind wir über eine Schleife durch alle Skizzen innerhalb eines Bauteiles gelaufen. Dieses Schleifenkonstruktionen sind in der Programmierung sehr wichtig, weil wir eben häufig wiederkehrende Prozesse für mehrere Dateien ausführen wollen.

Was wir bisher aber nicht besprochen haben, ist die Fehlerbehandlung. Ein Fehler kann in einem Programm immer mal auftreten und darauf sollten wir reagieren um zu verhindern, dass unserer Programm aus dem Tritt kommt. Dazu schauen wir uns hier ein paar Möglichkeiten an.

Errorhandling

Wer Programme nur für sich schreibt, muss beim Errorhandling nur das Abfangen, was er für nötig erachtet. Wenn das Programm aber auch von anderen Kollegen oder gar von Fremden genutzt wird, dann sollte es so sein, dass es unter keinen Umständen zu einem Programmabbruch mit Fehlermeldung kommt, weil das die meisten Leute verwirrt und sie nicht wissen, das sie tun sollen. Und Programme, die ohne Aufsicht laufen, dürfen sowieso nicht einfach hängenbleiben.

Die Fehlerbehandlung ist eine sehr komplexe Sache, weil man zum einem alle Eventualitäten im Ablauf berücksichtigen muss und zudem noch die Anwendungsfehler des Benutzer abfangen muss. Das kann in Arbeit ausarten ;) Im weitesten Sinne gehört dazu auch das Thema, das der Programmablauf nicht durch Meldungen durch den Inventor unterbrochen wird.

Inventormeldungen

Dieses Thema hatten wir schon. Programmabläufe werden unterbrochen, wenn der Inventor z.B. beim Öffnen einer Datei eine Dialogbox bringt, die wir erst wegklicken müssen, bevor es weiter geht. Dazu hatten wir im Beispiel mit dem PDF-Export der Zeichnung folgende Funktion genutzt:

ThisApplication.SilentOperation = True

Bei Programmende oder einem Programmabbruch durch einen Fehler muss der Wert wieder auf False gestellt werden, sonst bekommt der Anwender auch keine Dialoge mehr, was etwas blöd wäre.

ThisApplication.SilentOperation = False

Manche Meldungen lassen sich so aber auch nicht abstellen. Es besteht noch die Möglichkeit, den Inventor von "außen" zu steuern und als unsichtbaren Prozess zu starten, aber dafür können wir kein Inventor-VBA nutzen, weil der Invenor ja sichtbar da sein muss, wenn wir ein VBA-Programm darin ausführen wollen.

Mach nur weiter wenn...

Die nächste wichtige Sache ist das Abfragen, ob eine Aktion überhaupt ausführbar ist. Wir haben z.B. im letzten Beispiel erst geprüft, ob die Datei ein Bauteil und änderbar ist:

If oRefDoc.IsModifiable = True And oRefDoc.DocumentType = kPartDocumentObject Then

Oft kann ein Programm nur für einen bestimmte Dateityp genutzt werden und darf erst gar nicht weitermachen, wenn gerade die falsche Art von Datei im Inventor geöffnet ist.

If ThisApplication.ActiveDocument.DocumentType <> kDrawingDocumentObject Then
        MsgBox ("Programm funktioniert nur bei Zeichnungen! Bitte Zeichnung öffnen und nochmals probieren")
        Exit Sub
    End If

Was auch passieren kann: Das Programm wird ausgeführt und es ist keine Datei geöffnet. Dieser Fehler tritt zwar selten auf aber möglich ist er.

If ThisApplication.Documents.Count = 0 Then
    MsgBox ("Es ist keine Datei geöffnet. So wird das nichts werden!")
    Exit Sub
End If

Es wird Zeit, den VBA-Editor zu starten, unser VBA-Projekt zu laden und eine neue Public Sub zu machen. Darin stellen wir die SilentOperation auf True und machen die beiden Abfragen rein.

image

Wenn nun keine Datei geöffnet ist oder die aktuelle Datei ist keine Zeichnung kommt eine entsprechende Meldung und dann des Exit Sub wird das Programm komplett beenden.

Diese ganze Abfrage, ob das aktuelle Dokument (oder die aktuelle Komponenten, wenn man eine Baugruppe durchläuft) kann recht kompliziert werden, weil es manchmal nicht genügt, zu prüfen ob es sich um ein Bauteil handelt, sondern es muss vielleicht auch geprüft werden, ob es sich um eine abgeleitete Komponente oder ein Substitutionsdokument (Ableitung einer IAM) handelt. Dazu ist es hilfreich, sich mal die Eigenschaft des zu bearbeitenden Dokuments anzuschauen. Das kann in der Hilfe oder mittels eines Haltepunkts, der nach dem setzen eines Documentobjekts erfolgen.

Wir ändern die zweite Abfrage auf das Bauteilobjekt und setzen ein oDoc auf das aktuelle Dokument. Dann noch eine Haltepunkt auf End Sub und wir können uns das aktuelle Bauteildokument im Locals-Fenster anschauen.

image

Dort sehen wir z.B. das es eine Eigenschaft IsSubstitutePart gibt, die eben True oder False ist. Viele Dinge funktionieren nicht, wenn hier true steht.

Stellt sich die Frage, wie man da drauf kommen soll? Ganz einfach, testet eure Programme vorher mit einigen typischen Dateien die möglichst alle Arten von Daten enthält, z.B. Baugruppen mit Unterbaugruppen, schreibgeschützten Dateien, Blechen, iParts, abgeleitete Komponenten usw. Ich habe mir dazu eine Testbaugruppe erstellt, die alle möglichen Arten von Daten enthält. Macht euch Inventor Testprojekt, kopiert euch Dateien unterschiedlichster Art zusammen und fügt sie in eine IAM ein. Ihr könnt auch die Inventor Samples nutzen und euch daraus eine Testbaugruppe bauen.

On Error

Bisher haben wir alles mögliche unternommen, das ein Fehler erst gar nicht auftreten kann, indem wir z.B. geprüft haben, das der Dateityp stimmt, die Datei änderbar ist usw. Trotzdem kann es vorkommen, das ein Fehler auftritt, weil wir vielleicht nicht alle Eventualitäten bedacht haben oder Anwender sich noch "seltsamer" anstellt, als wir es uns in unseren dunkelsten Albträumen vorstellen können.

Wir wollen bei unserem Testprogramm einen Fehler provozieren, indem wir eine Division durch 0 durchführen, was ja bekanntlich nicht so wirklich geht. So sieht der Programmcodeabschnitt aus.

image

Wenn wir das Programm starten, bekommen wir eine Fehlermeldung, die sogar recht aussagekräftig ist: Division by zero.

image

Wer in dem Fenster auf "End" klickt beendet das Programm. Beim Klick auf Debug wird der Programmablauf in der fehlerverursachenden Zeile angehalten (ähnlich einem Haltepunkt) und man kann im Localfenster die Variableninhalte prüfen und sich Gedanken machen, warum ein Fehler aufgetreten ist.

Was wir nun wollen, ist das bei einem Fehler in einer Zeile diese einfach übergangen wird und das Programm mit der nächsten Zeile weitermacht. Wir brechen das Programm ab und ergänzen folgenden Zeile vor dem Block mit der Berechnung:

image

Starten wir nun das Programm, bricht es nicht mehr in der Zeile x = 10 / 0 ab sondern übergeht den Fehler und ruft die Messagebox auf, die als Wert für x inf ausgibt. Jetzt könnte man ja sagen "Spitze, dann sage ich meinem Programm einfach, das es bei einem Fehler mit der nächsten Zeile weitermachen soll und ich bin alle Probleme los". Leider ist es nicht so einfach. Ist eine Zeile essenziell für die weitere Programmausführung, wird aber übergangen, dann kommt das gesamte Programm aus dem Tritt. On Error Resume Next muss mit bedacht und Plan eingesetzt werden! Da die Anweisung für jeden Fehler in einer belieben folgenden Zeile gilt, muss dem Programm auch irgendwann gesagt werden, dass es jetzt nicht mehr einfach bei einem Fehler weitermachen soll. das erreicht man durch On Error goto 0

image

Im obigen Beispiel verursacht x = 20 / 0 wieder einen Fehler.

Will man bei einem Fehler nicht einfach mit der nächsten Zeile weiter machen (was meisten keine gute Idee ist, aber ich wiederhole mich) sondern eine Art Fehlerreoutine aufrufen, nutzt man on Error goto ...

On Error GoTo....

Wir entfernen alle On Error Anweisungen (oder kommentieren sie aus) und machen anstelle dessen am Programmanfang ein On Error goto Fehlerbehandlung

image

Ein Goto springt zu einem Sprungziel, mit dem entsprechenden Name. Und On Error sollte klar sein. In Summe: Bei Fehler springe zum Sprungziel mit Namen Fehlerbehandlung.

Jetzt müssen wir das Sprungziel auch noch definieren. Das machen wir am Ende des Programm. Einfach den Sprungzielnamen gefolgt von einem Doppelpunkt schreiben:

image

Führen wir jetzt das Programm aus, springt wir direkt zu Fehlerbehebung und danach kommt nur noch End Sub, d.h. das Programm ist zu Ende. Was nicht passiert, ist das SilentOperation = False gesetzt wird (dazu müssten wir Fehlerbehandlung: vor die Zeile setzen) und es kommt auch keine Fehlermeldung. Der Anwender merkt nur, das nichts passiert. Wir ergänzen also unterhalb des Sprungziels zumindest eine Meldung und wir wollen, das im Fehlerbehandlungsblock auf alle Fälle SilentOperation = False gestzt wird.

image

Führen wir jetzt unser Programm aus, bekommen wir die entsprechende Meldung, SilentOperation wird ausgeschaltet und dann ist das Programm vorbei.

Jetzt machen wir eine kleine Änderung im Programm, so dass kein Fehler mehr auftritt.

image

Führen wir das Programm nun aus, bekommen wir eine Meldungsbox mit dem Berechnungsergebnis und dann kommt leider aber die Fehlermeldung, weil das Programm einfach über die Sprungmarke spaziert und den Code darunter ausführt. Wir müssen also das Programm vor der Sprungmarke beenden. Wenn wir dort angekommen sind, war ja alles in Ordnung. Dazu setzen wir direkt vor die Sprungmarke ein Exit Sub. Das Sprungziel Fehlerbehandlung wird nur noch erreicht, wenn ein Fehler auftritt, was ja auch genau das ist, was wir wollen.

image

Jetzt bekommen wir zwar eine Meldung, das ein Fehler aufgetreten ist, aber wir wissen nicht welcher. In unserem Fall war es ja Division by Zero. Wenn ein Fehler auftritt, gibt es ein Objekt Err das z.B. eine Eigenschaft Description hat, das wir uns in der Dialogbox anzeigen lassen wollen. Dazu verknüpfen wir den Meldungstext mittels des & dann kommt ein Zeilenumbruch und dann wieder ein & und der Fehlermeldungstext.

image

Jetzt stellen wird oben wieder auf / 0 um und starten das Programm. Wir bekommen nun neben der Meldung auf die Fehlerbeschreibung, die uns vielleicht hilft, das Problem besser zu verstehen.

image

So sieht unser fertiges Programm aus:

image

Und hier in Textform:

Public Sub Fehler()
On Error GoTo Fehlerbehandlung
ThisApplication.SilentOperation = True
    If ThisApplication.Documents.Count = 0 Then
        MsgBox ("Es ist keine Datei geöffnet. So wird das nichts werden!")
        Exit Sub
    End If
    
    If ThisApplication.ActiveDocument.DocumentType <> kPartDocumentObject Then
        MsgBox ("Programm funktioniert nur bei Bauteilen! Bitte Bauteil öffnen und nochmals probieren")
        Exit Sub
    End If
    
    Dim oDoc As PartDocument
    Set oDoc = ThisApplication.ActiveDocument
    
    'On Error Resume Next
    Dim x As Double
    x = 10 / 0
    MsgBox (x)
    'On Error GoTo 0
    x = 20 / 1
    
    ThisApplication.SilentOperation = False
    
    Exit Sub
Fehlerbehandlung:
    MsgBox ("Es ist ein Fehler aufgetreten. Tut mir Leid :(" & vbCr & Err.Description)
    ThisApplication.SilentOperation = False
End Sub

Das war's für heute.Bis zum nächsten mal bei unserem kleine Programmierkurs.

PS: Weitere Infos zum Errorhandling gibt es auch in der Hilfe.

image

Hier geht's weiter zu Teil 8.

Kommentare:

War der Beitrag hilfreich oder hast du eine Ergänzung dazu?
Ist noch eine Frage offen?
Ich freue mich auf deine Rückmeldung!

Related Posts Plugin for WordPress, Blogger...
Inventor FAQ Newsletter. Emailadresse: