none
Excel Fehlerdialoge behandeln RRS feed

  • Frage

  • Hallo,

    wir haben eine C# .NET 4 Anwendung, die via Interop v14 Excel-Dateien aus einem bestimmten Verzeichnis öffnet, diese als PDF wieder abspeichert und dann an die Kunden verteilt (E-Mail, Brief, Fax usw.).

    Dieses Tool macht Probleme, wenn die Excel-Dateien nicht wie erwartet vorliegen. Beispielsweise handelt es sich um eine Datei, die gar nicht ohne weiteres von Excel geöffnet werden kann (Formatfehler) oder die Verweise bzw. Formeln enthält, die nicht aktualisiert werden können. Kommt soetwas vor, dann steht das ganze Tool, da Excel im Hintergrund auf die Bestätigung seines Fehlerdialogs wartet. Da das ganze automatisiert abläuft, haben wir damit große Probleme.


    Meine Frage ist also, wie ich die Fehlerdialoge, die Excel unter Umständen ausgibt, behandeln kann, ohne dass der ganze Prozess zum Stillstand kommt. Die Dateien sollen gar nicht erst verarbeitet werden, wenn sich ein Fehler ergibt. Es wäre also keine Hilfe, wenn ich die Dialoge einfach unterdrücke oder z.B. das Aktualisieren der Formeln deaktiviere.

     

    Ich hoffe es war nicht zu undeutlich ausgedrückt und ihr habt dazu vielleicht eine zündende Idee!

     

    Beste Grüße, Sven

    Montag, 5. Juli 2010 09:53

Alle Antworten

  • Hallo Sven,

    • Du schriebst: "Dieses Tool macht Probleme, wenn die Excel-Dateien nicht wie erwartet vorliegen. Beispielsweise handelt es sich um eine Datei, die gar nicht ohne weiteres von Excel geöffnet werden kann (Formatfehler) oder die Verweise bzw. Formeln enthält, die nicht aktualisiert werden können. Kommt soetwas vor, dann steht das ganze Tool, da Excel im Hintergrund auf die Bestätigung seines Fehlerdialogs wartet. Da das ganze automatisiert abläuft, haben wir damit große Probleme."

    Nun, Du musst ja aber erst erkennen, dass diese Datei ein ungültiges Format oder Deinen Ansprüchen nicht gerechte Formeln hat. Das geht in den meisten Fällen eben darüber, dass man die Dialoge unterdrückt und eben danach die Datei gegen seine Ansprüche validiert. Genau diese Aufgabe hatte ich zumindest früher mal so umgesetzt.

    Wenn Du wüsstest, dass nur gewisse Formate zum Einsatz kommen, wäre ggf. auch an .NET Framework Klassen zu denken:

    [What is the Difference Between the System.IO.Packaging and DocumentFormat.OpenXml.Packaging Namespaces? - Eric White's Blog - Site Home - MSDN Blogs]


    ciao Frank
    Montag, 5. Juli 2010 11:30
  • Hallo Sven,

    Habt Ihr es schon mal damit versucht?

    using Excel = Microsoft.Office.Interop.Excel;
    using OfficeCore = Microsoft.Office.Core;
    
    
    //...
    
    Excel.Application excelApp = new Excel.Application();
    excelApp.AlertBeforeOverwriting = false;
    excelApp.AskToUpdateLinks = false;
    excelApp.DisplayAlerts = false;
    excelApp.FeatureInstall = OfficeCore.MsoFeatureInstall.msoFeatureInstallNone;
    

    Die Zeilen habe ich einer älteren Anwendung entnommen, vielleicht helfen Sie aber auch Euch weiter.

    Gruß
    Marcel

    Montag, 5. Juli 2010 13:02
    Moderator
  • Nachtrag: Neben der OpenXML/IO.Packaging Methode gäbe es ggf. natürlich auch noch die Möglichkeit über einen OleDbProvider

    [How to query and display excel data by using ASP.NET, ADO.NET, and Visual C# .NET]
    http://support.microsoft.com/default.aspx?scid=kb;en-us;306572

     


    ciao Frank
    Montag, 5. Juli 2010 13:20
  • Hallo Marcel,

    Du schriebst: "using Excel ....",   ok, der Code betrifft die Unterdrücks-Methode, zu der Sven ja sagte: "Es wäre also keine Hilfe, wenn ich die Dialoge einfach unterdrücke oder z.B. das Aktualisieren der Formeln deaktiviere.". Aber gut - es ist auch meine Meinung, dass es wohl kaum anders geht, ausgenommen: OpenXML- / IO.Packaging- Methode / OleDb-Methode.

    Bei dem Code sollte man aber (wenn schon) dann ggf. noch das Schliessen der App als Beispiel dazuposten, also etwa:

    private void ShutDownExcel() 
    {
     if (mExcelApp != null) 
     {
      mExcelApp.DisplayAlerts = true;
      mExcelApp.Quit();
    
      System.Runtime.InteropServices.Marshal.ReleaseComObject(mExcelApp);
      mExcelApp = null;
     }
    
     // Clean up memory so Excel can shut down.
     GC.Collect();
     GC.WaitForPendingFinalizers();
    
     // The GC needs to be called twice in order to get the
     // Finalizers called - the first time in, it simply makes
     // a list of what is to be finalized, the second time in,
     // it actually the finalizing. Only then will the
     // object do its automatic ReleaseComObject.
     GC.Collect();
     GC.WaitForPendingFinalizers();
    }
    

    [A Day in the Life: Digipede: Distributing Excel Computations - Excel Automation Considerations]
    http://krgreenlee.blogspot.com/2006/03/digipede-distributing-excel_10.html

     


    ciao Frank
    Montag, 5. Juli 2010 13:32
  • Hallo Frank,

    Man könnte alternativ den Excel-Interop-Teil auch in einer separaten, entladbaren AppDomain implementieren. Dann noch einen Timer und ein TimeOut bei dessen Erreichen die AppDomain entladen wird. Und weiter geht's.

    Microsoft .NET Development for Microsoft Office: AppDomain Unloading
    http://msdn.microsoft.com/en-us/library/aa679807(office.11).aspx

    Gruß
    Marcel

    Montag, 5. Juli 2010 15:05
    Moderator
  • Hallo Marcel,

    Du schriebst: > "Alternative AppDomain Unloading ..."

    ja, Du meinst um: "Excel zu schliessen" eine Alternative.
    Unter .NET kann man ja zu 99.9% Alternativ-Methoden angeben.
    Deswegen schreibe ich auch immer schon "zum Beispiel" etc. o.ä.

    Ich hatte in meinem Posting die GC-Methode genommen, weil sie aus meinen Erfahrungen der C# NNTP-NG am häufigsten gewählt wurde. Es gibt hier - wie immer - mehrere Methoden.


    ciao Frank
    Montag, 5. Juli 2010 17:30
  • Hallo Frank,

    So ist es es. Mehrere Wege führen nach Rom. Und nein, ich meine nicht nur eine Alternative um Excel zu schließen, sondern dachte auch an die Möglichkeit, Excel sicher zu entladen, wenn es eine gewisse Zeitspanne nicht mehr reagiert (weil es z.B. auf Benutzerinteraktion wartet), was im Szenario von Sven vielleicht hineinpaßt.

    Gruss
    Marcel

    Montag, 5. Juli 2010 17:57
    Moderator
  • Hallo Marcel,

         Du schriebst: "so ist es ...".

    ja, Du kannst ja ggf. mal "zitieren", dann weiss man auch, was gemeint ist.
    Vielleicht <blockquote> oder indirekten Stil wie oben.


         Du schriebst:
        "wenn es eine gewisse Zeitspanne nicht mehr reagiert (weil es z.B. auf
          Benutzerinteraktion wartet), ...

    Solche Timeout-Zeiten sind ~potentiell recht unsauber.
    Man kann zum einen nie sagen, wie solche Zeiten eingestellt werden sollen und garantiert bekommt man den Murphy-Fall, wo man zu früh oder zu spät abbricht.
    Ein Rechner kann durch bestimmte Umstände kurzzeitig deutlich langsamer werden (und solche Dinge), das ist keine gute Methode IMHO. Zum anderen können beim harten Abbruch etwa allokierte globale Ressourcen ggf. nicht mehr freigegeben werden. Also wohl (zumindest) besser mit Lebenssignal-Mutex Signal-Thread o.ä. absichern.

    IMHO besser durch das Objekt-Modell sauber prüfen, was mir hier möglich erscheint. Schliesslich deaktivierst Du ja die Alerts und das Warten auf Benutzereingaben blockiert ja nicht die Automation.

    Aber es geht vielleicht etwas zu weit in die Details. Lassen wir es doch mal so stehen und schauen, ob für Sven sowas überhaupt in Frage kommt, weil er es ja im Prinzip in seiner Frage ausgeschlossen hat.

     

     


    ciao Frank
    Montag, 5. Juli 2010 19:22
  • Hallo Frank,

    Ich bin mir sicher, Sven kann auch lesen.

    Gruß
    Marcel

    Montag, 5. Juli 2010 19:27
    Moderator
  • Hallo Marcel,

    > Sven kann auch lesen

    ich weiss zum Beispiel jetzt nicht, auf welchen Teil irgendeines Satzes Du das jetzt meinst. So wird es auch anderen gehen - das ist zumindest meine Erfahrung vieler Jahre aus den Postings. Aber wenn Du nicht zitieren willst (was ich jetzt aus Deinen Postings vermute), dann weiss ich das jetzt und frage da nicht mehr nach.

    Insgesamt redet man ohne Zitieren öfter aneinander vorbei, weil Missverständnisse auftreten, o.ä.. Ich mache da aber jetzt mal EOT (meinerseits bzgl. dieses Zitieren-Themas), um nicht die C# Gruppe mit OT-Dingen zu füllen.

     


    ciao Frank
    Montag, 5. Juli 2010 20:03
  • Nun, Du musst ja aber erst erkennen , dass diese Datei ein ungültiges Format oder Deinen Ansprüchen nicht gerechte Formeln hat. Das geht in den meisten Fällen eben darüber, dass man die Dialoge unterdrückt und eben danach die Datei gegen seine Ansprüche validiert . Genau diese Aufgabe hatte ich zumindest früher mal so umgesetzt.


    Hallo Frank,

    bitte nicht meinetwegen streiten, das ist es nun wirklich nicht wert!

    Ich verstehe, was du mit obigem meinst, glaube aber, es passt für meine Anforderung nicht so richtig. Prinzipiell ist jede Datei im Format xls bzw. xlsx erlaubt. Sie muss eben nur den Anforderungen von Excel genügen. Ein dummes Beispiel: Ich habe eine txt-Datei. Diese benenne ich von Hand in xls um. Wenn ich diese dann mit Excel öffnen möchte, sagt mir jenes, dass es sich nicht um das erwartete Format handelt. Wenn ich diese Meldung irgendwie verarbeiten könnte, wäre mir sehr geholfen. Ich wüsste nicht, wie ich sonst validieren soll?!


    Ähnlich verhält es sich bei den Formeln. Excel spuckt doch ebenfalls eine Fehlermeldung aus, wenn bestimmte Verweise nicht aktualisiert werden können, oder? Diese Infos würde ich gerne weiterverarbeiten und nicht das ganze Dokument nach Fehlern durchkämmen. Vielleicht bin ich aber auch auf dem völlig falschen Dampfer.

     

    Dienstag, 6. Juli 2010 05:01
  • Hallo Marcel,

    das reine Unterdrücken der Fehlermeldung wollte ich eigentlich vermeiden. Ich will gerne wissen, ob bzw. was genau an der Datei fehlerhaft ist und habe gehofft, die Dialoge, die Excel ausgibt, behandeln bzw. verarbeiten zu können. Deine Idee wäre praktisch der letzte Ausweg, den ich aber ungern nehmen möchte ;)

    Beste Grüße, Sven

    Dienstag, 6. Juli 2010 05:06
  • Hallo Sven,

    Office wurde für die interaktive Benutzung entwickelt. Daher die Fehlermeldungen in der GUI. Wenn die Fehlerunterdrückung für Euch nicht in Betracht kommt, könnte man das Tool, das Excel-Dateien verarbeitet, dahingehend modifizieren, dass es eine gewisse Zeit auf Excel wartet, um dann bei Nichtreagieren Excel aus der temporären AppDomain zu entladen und neu zu laden. Ich weiß sehr wohl, dass es nicht das ist, was Du dir vorgestellt hast, was besseres fällt mir im Moment aber nicht ein ;-)

    Ob eine Excel-Datei "fehlerhaft" ist, läßt sich m.E. erst nach dem Versuch sagen, die Datei zu öffnen.

    Nachtrag: Oft reicht die falsche Übertragung eines einzigen Bytes um das interne structured storage Format lahm zu legen. Ich habe schon vieles gesehen in diesem Bereich, und man müßte schon *einiges* unternehmen um z.B. ein korruptes VBA Project Header etc über Code als "fehlerhaft" zu erkennen. Bei jeder kleinsten Abweichung vom erwarteten Format, würde Excel eine Meldung bringen, daher kann man im Vorfeld nicht mit Sicherheit sagen, ob eine Datei den Erwartungen von Excel entspricht oder nicht. Mein Vorschlag: Divide et impera. Alle Dateien aussondern, die nicht innerhalb eines festgelegten Zeitraums (z.B. 2 Minuten - hängt von dem ab, was euer Tool macht) verarbeitet werden könnnen.



    Viele Grüße
    Marcel

    Dienstag, 6. Juli 2010 05:21
    Moderator
  • Hallo Sven,

    > Wenn ich diese Meldung irgendwie verarbeiten könnte, wäre mir sehr geholfen.
    > Ich wüsste nicht, wie ich sonst validieren soll?!

    ich verstehe Dein Ansinnen. Aber es gibt da AFAIK wirklich nur die Methoden die ich nannte:

    • Unterdrückung der Meldungen und ggf. spätere Auswertung über Excel-Objektmodell. Code wurde beispielhaft von Marcel und mir gepostet.
    • Vorherige Validierung über System.IO.Packaging. Bei einer Exception kannst Du hier reagieren, indem Du weisst, dass es nicht das Format ist.
    • Vorherige Validierung über DocumentFormat.OpenXml.Packaging. Sonst analog zu oben.
    • Vorherige Validierung über OleDbProvider. (Klar, theoretisch auch binär gemäß Spec durchlesbar)
      [Links zu den Themen sind weiter oben]

    > Ähnlich verhält es sich bei den Formeln. Excel spuckt doch
    > ebenfalls eine Fehlermeldung aus, wenn bestimmte Verweise
    > nicht aktualisiert werden können, oder?

    ja, aber auch die kann man AFAIK abschalten. Man kann oft auch über ein einfaches try-catch in der C# Automation arbeiten.



    > Diese Infos würde ich gerne weiterverarbeiten und nicht
    > das ganze Dokument nach Fehlern durchkämmen.

    ja, das ist verständlich. Aber nach einer Exception kannst Du ja eigentlich diese ggf. loggen (o.ä.) und beenden, sodass ein "Durchkämmen" ja nicht nötig ist.

     


    ciao Frank
    Dienstag, 6. Juli 2010 05:51