Excel UDF: COM Error mit _Excel_Open

  • Hallo ihr alle,

    ich trau mich jetzt doch mal an meinen ersten Post ran, weil ich auch nach längerer Suche in den meist wirklich guten Forumsbeiträgen noch keine Lösung für mein Problem gefunden habe.

    Ich arbeite mit Folgendem:

    • AutoIT 3.3.12 (mit SciTE 3.4.4)
    • Windows 7 Ultimate (64 Bit)
    • MS Office 2010 SP2 (32 Bit)

    Ich habe ein Skript entwickelt, um eine Excel-Tabelle mit Werten aus einer XML-Datei zu füllen. Das funktioniert grundsätzlich auch wunderbar.

    Nervig ist nur, dass ich beim Öffnen von Excel über _Excel_Open (aus Excel.au3) immer einen "COM Error with DOM" erhalte, wenn Excel noch nicht läuft. Hier mal die Ausgabe mit eingebundener Debug.au3:

    @@ DEBUG COM Error encountered in ParseStudioReport.au3 (66) :
    Number = 0x80020006 (-2147352570)
    WinDescription = Unbekannter Name.
    Description =
    Source =
    HelpFile =
    HelpContext =
    LastDllError = 0
    Retcode = 0x00000000

    Ich verwende folgende Anweisung, um Excel zu öffnen:

    [autoit]

    Local $oExcelH = _Excel_Open()

    [/autoit]


    Interessanterweise verhindert dieser COM Error aber nicht die weitere Ausführung des Skripts. Der Fehler wird also angezeigt, und dann geht alles problemlos weiter.

    Die Zeile 66, die als Ursache des Fehlers angegeben wird, scheint sich übrigens nicht auf mein eigenes Skript zu beziehen, denn da wird an der Stelle nur eine einfache Integer-Variable abgefragt, die mit irgendwelchen COM-Objekten überhaupt nichts zu tun hat (die kommen erst ab Zeile 151 ins Spiel). Offensichtlich stolpert mein System über Zeile 66 in der Excel.au3, die zur Funktion _Excel_Open gehört:

    [autoit]

    If Not $bForceNew Then $oExcel = ObjGet("", "Excel.Application")

    [/autoit]


    Ich hab es auch schon mit der Anweisung #AutoIt3Wrapper_UseX64=N oben in meinem Skript probiert (obwohl ich mich bei der Installation von AutoIT ohnehin für die 32-Bit-Variante entschieden hatte), was aber bei der kompilierten Version (.exe) keine Abhilfe gebracht hat.

    Weiß vielleicht jemand Abhilfe? (Wie gesagt, der COM Error ist zwar nervig, aber kein Showstopper.)
    Vielen Dank schon mal,
    caseelse

    Einmal editiert, zuletzt von caseelse (15. August 2014 um 12:42)

  • Abhilfe? Ja, ignorieren.
    Ernsthaft. Das ist in diesem Fall kein Fehler, sondern eine Info. Die UDF versucht sich zuerst an eine laufende Excel Instanz anzuhängen. Findet sie diese nicht, dann wird der COM Error angezeigt und die UDF erzeugt eine neue Excel Instanz.
    Kannst Du umgehen, wenn Du den Parameter $bForceNew auf True setzt.

  • Hallo water,

    Kannst Du umgehen, wenn Du den Parameter $bForceNew auf True setzt.

    Prima, vielen Dank. Ich hab's getestet und jetzt läuft's ohne den Fehler :thumbup:

    Mir erschließt sich zwar die Logik nicht so ganz, denn der Sinn dieser Funktion ist es doch gerade, das Ganze zu automatisieren (also überprüfen, ob schon eine Instanz läuft, und nur, wenn dies nicht der Fall ist, eine neue Instanz starten), aber wo kann man sich im Leben schon auf Logik verlassen ;)

    Dir jedenfalls herzlichen Dank für deine Hilfe!

  • Aber genau das macht die Funktion ja. Aber bei der Prüfung wird der COM error verursacht wenn Excel noch nicht läuft. Alles klar?

  • Ja, das ist mir schon klar. Aber das heißt auch, dass grundsätzlich eine neue Excel-Instanz gestartet werden muss, wenn man den COM-Fehler vermeiden will, und zwar auch dann, wenn schon eine Instanz läuft. Dann könnte man sich die Prüfung ja auch eigentlich sparen, oder?

  • Du verstehst mich miss!
    Wenn bereits eine Excel Instanz läuft und der Parameter $bForceNew nicht gesetzt ist, dann wird NIE eine neue Instanz erzeugt:

    Excel läuft, _Excel_Open():
    Die UDF hängt sich an die bestehende Instanz. Keine COM Fehlermeldung

    Excel läuft nicht, _Excel_Open():
    Die UDF versucht sich an eine bestehende Instanz zu hängen. Da keine besteht, führt das zum COM error. Danach wird eine neue Instanz gestartet. COM Fehlermeldung

    Excel läuft, _Excel_Open(Default, Default, Default, Default, True):
    Es wird eine neue Excel Instanz erzeugt ohne auf eine bestehene zu prüfen. Keine COM Fehlermeldung

    Excel läuft nicht, _Excel_Open():
    Es wird eine neue Excel Instanz erzeugt ohne auf eine bestehene zu prüfen. Keine COM Fehlermeldung

  • Ah, ich glaube, so langsam dämmert es mir. Lass es mich noch mal versuchen:

    Die UDF erkennt aufgrund des COM-Fehlers nach dem Aufrufen von ObjGet("", "Excel.Application") (Zeile 66), dass noch keine Excel-Instanz läuft, und erstellt erst dann mit ObjCreate("Excel.Application") (Zeile 68 ) eine neue Excel-Instanz. Stimmt das so?

    Jetzt fände ich noch interessant, ob man die Ausgabe des COM-Fehlers, die ja eigentlich nur der internen Information des Skripts selbst dient, irgendwie unterdrücken könnte, damit der Benutzer davon nichts mitbekommt? Dann müsste man das Skript nicht zwingen, auch dann eine neue Excel-Instanz zu erstellen, wenn dies gar nicht notwendig ist.

  • Jetzt fände ich noch interessant, ob man die Ausgabe des COM-Fehlers, die ja eigentlich nur der internen Information des Skripts selbst dient, irgendwie unterdrücken könnte, damit der Benutzer davon nichts mitbekommt? Dann müsste man das Skript nicht zwingen, auch dann eine neue Excel-Instanz zu erstellen, wenn dies gar nicht notwendig ist.


    Das wird doch in der Konsole ausgegeben, so weit ich weiß. (Oder?)

    Wenn du das Skript dann kompilierst, sieht der Nutzer das dann sowieso nicht!

    There's a joke that C has the speed and efficieny of assembly language combined with readability of....assembly language. In other words, it's just a glorified assembly language. - Teh Interwebz

    C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do, you blow off your whole leg. - Bjarne Stroustrup
    Genie zu sein, bedeutet für mich, alles zu tun, was ich will. - Klaus Kinski

  • Schalte das Debuggen erst nach _Excel_Open ein?
    Um zu prüfen, ob _Excel_Open erfolgreich gelaufen ist, prüfe einfach @error und @extended entsprechend der Hilfe.

    Zitat

    Dann müsste man das Skript nicht zwingen, auch dann eine neue Excel-Instanz zu erstellen, wenn dies gar nicht notwendig ist.

    Wer zwingt wen? Das macht doch alles _Excel_Open intern - oder machst Du da noch irgendwas von Hand?
    Zeig mal Deine Hände - äh - Dein Skript.

  • Wer zwingt wen? Das macht doch alles _Excel_Open intern - oder machst Du da noch irgendwas von Hand?
    Zeig mal Deine Hände - äh - Dein Skript.

    Nee, zwingen meine ich mit $bForceNew = True (engl. "to force" heißt auf Deutsch "zwingen"). Dadurch wird doch _Excel_Open angewiesen, IMMER eine neue Instanz zu erstellen, egal ob schon eine läuft oder nicht. Oder verstehe ich das falsch?

  • Zitat

    Nee, zwingen meine ich mit $bForceNew = True (engl. "to force" heißt auf Deutsch "zwingen"). Dadurch wird doch _Excel_Open angewiesen, IMMER eine neue Instanz zu erstellen, egal ob schon eine läuft oder nicht. Oder verstehe ich das falsch?

    Nö, das verstehst Du schon richtig.

  • Hm, bei mir kommt das immer als Extra-Meldung hoch (auch nach dem Kompilieren)

    Dann hast Du irgendwo einen COM error handler installiert. Such mal nach "ObjEvent" in Deinem Skript.

  • Dann hast Du irgendwo einen COM error handler installiert. Such mal nach "ObjEvent" in Deinem Skript.

    Nicht wirklich. Ich hatte irgendwann mal beim Suchen nach einem Tipp, wie ich diese nervigen Meldungen loswerden könnte, den Hinweis gefunden, man könne Folgendes am Skriptanfang einfügen:

    [autoit]

    #include <Debug.au3>
    _DebugSetup()
    _DebugCOMError()

    [/autoit]


    Dadurch wurde mir das Ganze aber auch nur in einer anderen Fenstersorte angezeigt. Und die drei Zeilen hab ich schon lange wieder auskommentiert. Daran kann's nicht liegen.

  • Ha, Moment. Ich hab jetzt mal meine anderen Includes durchgeschaut und in _XMLDomWrapper gibt es in der von mir verwendeten Funktion _XMLFileOpen Folgendes:

    [autoit]

    $oXMLMyError = ObjEvent("AutoIt.Error")
    If $oXMLMyError = "" Then
    $oXMLMyError = ObjEvent("AutoIt.Error", "_XMLCOMEerr") ; ; Initialize SvenP 's error handler
    EndIf

    [/autoit]


    Kann sich das auf mein gesamtes Skript auswirken?

  • Irgendwo fliegt noch ein objEvent rum.
    Entweder in Deinem Skript oder in einem Include. Vielleicht verwendest Du irgendwo eine alte Version einer UDF?

    Ruf mal mit Strg+F7 die Compile Funktion auf -> Reiter "Au3Stripper" -> "Run Au3Stripper before compilation" markieren und Skript kompilieren. Im Sourceverzeichnsi liegt nun Scriptname_Stripped.au3
    Such hier mal nach objEvent.

  • So isses. Ruf einfach _Excel_Open vor dem ersten XML Befehl auf.

  • So isses. Ruf einfach _Excel_Open vor dem ersten XML Befehl auf.

    Wahnsinn, worauf man da alles achten muss. Na ja, immerhin ist das mein erstes ernsthaftes AutoIT-Skript. Es gibt also noch viel Luft nach oben 8|

    Water, vielen Dank für deine geniale Hilfe!! :thumbup:

  • Gerne :)
    Für Dein erstes Skript hast Du Dir natürlich ein eher komplexes Thema ausgesucht. Und die Handhabung von COM Fehlern ist in AutoIt bis inkl. Version 3.3.8.1 nicht wirklich genial gelöst. Ältere UDFs müssen auf die nun bessere Variante der Fehlerbehandlung erst umgestellt werden.