Laden...

EXCEL wirklich schliessen

Erstellt von cel vor 17 Jahren Letzter Beitrag vor 4 Jahren 42.152 Views
C
cel Themenstarter:in
6 Beiträge seit 2007
vor 17 Jahren
EXCEL wirklich schliessen

Bei der Erstellung einer Applikation, die mit EXCEL arbeitet stiess ich auf das Problem, dass sich EXCEL nicht sauber schliessen lässt. Die Artikel in diesem Forum waren recht hilfreich, die endgültige Lösung habe ich aber in dem grandiosen Artikel von Scott Rutherford gefunden. Die dort beschriebene Lösung ist in Visual Basic geschrieben und lässt sich eins zu eins auf C# übertragen:

Bei dem Versuch EXCEL wieder sauber zu schliessen tritt das Problem auf, dass man die Applikation zwar schliessen und beenden kann, der Hauptprozess aber im Hintergrund erhalten bleibt. Das frisst nicht nur Ressourcen, sondern blockiert unter Umständen auch (temporäre) Dateien, die man nicht löschen, ändern oder überschreiben kann.

Der typsiche Ausstieg sieht wohl ao aus:

// --- alles ordentlich schliessen
excelWorkbook.Close(false, MISSING, MISSING);
 excelApp.Application.Quit();
 excelApp.Quit();

// --- COM Objekte wieder freigeben
Marshal.ReleaseComObject(excelWorksheet);
Marshal.ReleaseComObject(excelWorkbook);
Marshal.ReleaseComObject(excelApp);

// --- variablen nullen, damit GC eine Chance hat den Speicher zu raeumen
excelWorksheet = null;
excelWorkbook = null;
excelApp = null;

// --- evtl. GC direkt aufrufen ... muss man aber nicht
//GC.Collect();
 //GC.WaitForPendingFinalizers();

Das reicht aber nicht aus. Um EXCEL **wirklich **zu beenden, muss man den Prozess abschiessen!

Nun ist die Frage natürlich, wie kommt man den Prozess ran? Antwort: wir geben EXCEL bei der Initialisierung eine 'Markierung' mit:

string GuiId  = System.Guid.NewGuid().ToString().ToUpper();
excelApp.Caption   = GuiId; // 'unser' EXCEL eindeutig markieren!

Hierüber können wir später 'unser' - und nur unser - EXCEL Fenster wiederfinden:

IntPtr hWnd = FindWindow(null, GuiId);

.. und dann die Prozess-ID identifizieren:

int iProcID;
GetWindowThreadProcessId(hWnd, out iProcID);    

Achtung:

GetWindowThreadProcessId

verlangt als 2. Argument eine Zeiger-Referenz auf eine

int 

Variable. In C# muss daher unbedingt das

out 

benutzt werden!

Mit der Prozess-ID kommen wir dann wieder sehr leicht an den EXCEL Prozess ran:

Process p = Process.GetProcessById((int)iProcID);

Und nun hat EXCEL endgültig verloren:

p.CloseMainWindow();    
p.Refresh();
p.Kill();

Dann noch ein letzter Hinweis: um die oben genannten Funktionen

FindWindow 

und

GetWindowThreadProcessId

benutzen zu können, müssen die vorab in der Klasse sauber deklariert werden:

[DllImport("user32")]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);

Ich habe ein komplettes Beispiel angehängt. Wenn man das ausführt und den Task-Manager offen hat, kann man sehen, wie der EXCEL Prozess wieder verschwindet.

A
72 Beiträge seit 2006
vor 17 Jahren

woa super, es wäre schön wenn man das als FAQ beitrag sichtbar machen kann. ich hatte auch schon das problem, bin aber nicht auf die idee gekommen die besagte Markierung mitzugeben.

gut gemacht, ich danke dir!

3.728 Beiträge seit 2005
vor 17 Jahren
Hart abschießen

Es kann nicht die Lösung sein, einfach den Prozess abzuschießen. Das ist absolut dreckig.

Wenn der Excel-Prozess sich nicht richtig beendet, stimmt was nicht. Du solltest lieber die Ursache finden und sie beheben, statt nur die Auswirkungen zu bekämpfen.

Vielleicht ist ein AddIn etc. geladen, welches Excel am beenden hindert?

Ich hatte dieses "Excel beendet sich nicht"-Problem noch nicht. Es muss also irgendwas an Deiner Umgebung nicht stimmen. Excel an sicht funktioniert und beendet auch korrekt (So meine Erfahrung!).

C
cel Themenstarter:in
6 Beiträge seit 2007
vor 17 Jahren

Nein, dem ist nicht so. Spätestens wenn EXCEL mehrfach geöffnet wird, bleiben die Prozesse hängen, in der Regel aber schon nach einmaligem öffnen. Microsoft weist in den Foren selber auf diesen Bug hin. Es schliessen sich zwar alle Fenster, d.h. die Applikation ist vermeintlich nicht mehr da, aber im Task-Manager kann man den Prozess noch sehen.

A
72 Beiträge seit 2006
vor 17 Jahren
???

@Rainbird: das kann ich nicht bestätigen, da geb ich cel Recht.
selbst wenn ich excel nicht aus einer meiner applikationen öffne, sind teilweise die prozesse noch offen.
Aus c# heraus das selbe spiel. wenn (wenn nötig) alles gespeichert ist, ist es kein thema das man excel einfach abschiesst. solang man auch den richtigen prozess erwischt, daher hat er die Lösung schon gut getroffen.

@cel: Hast du was dagegen wenn ich mir deinen Beitrag kopiere? ^^

C
cel Themenstarter:in
6 Beiträge seit 2007
vor 17 Jahren

Ich dachte ein Forum ist dazu da, dass man Ergebnisse teilit und wiederverwendet =kopiert?

A
72 Beiträge seit 2006
vor 17 Jahren

ja kopieren in dem sinne das ich die lösung dazu, die sehr nützlich ist, in mein forum stelle ^^
vllt findet das ja jemand auch so hilfreich und muss nicht erst lange im internet suchen.
weil bei mir im forum treffen sich nur die selben leute, die nur programmieren (beruf ^^)

3.728 Beiträge seit 2005
vor 17 Jahren
Excel-Mysterien

Bei mir hat sich Excel bis jetzt immer sauber geschlossen. Ich habe zu Hause allerdings nur Excel 2000. Tritt das erst bei neueren Versionen auf?

Was muss ich tun, um das zu simulieren?

Hat jemand von euch vielleicht einen Link auf die Microsoft-Foren, in denen das diskutiert wurde?

U
195 Beiträge seit 2006
vor 17 Jahren

Also ich kann dieses Problem nur bestätigen. Nutze Excel 2003 und greife über PIA's auf Excel zu.

Hier mal die Code-Stelle, an der ich Excel schliesse:


if (chkShowExcel.Checked)
            {
                excelApp.Visible = true;
            }
            else
            {
                //Excel schliessen
                excelWorkbook.Close(false,missing,missing);
                excelApp.Application.Quit();
                excelApp.Quit();

                //Variablen nullen
                excelApp = null;
                excelSheets = null;
                excelWorkbook = null;
                excelWorksheet = null;

                //Speicher aufräumen lassen (Muss nicht gemacht werden, aber doppelt hällt bekanntlich besser ;) )
                GC.Collect();
                GC.WaitForPendingFinalizers();
            } 

Auch bei mir bleibt der Prozess offen. Und ich hab keine Ahnung warum 😁

Vielleicht könnte mir ja jemand beiläufig erklären, wofür das gemacht wird:


 // --- COM Objekte wieder freigeben
                Marshal.ReleaseComObject(excelWorksheet);
                Marshal.ReleaseComObject(excelWorkbook);
                Marshal.ReleaseComObject(excelApp);
T
147 Beiträge seit 2005
vor 17 Jahren

Hallo,

auch ich habe mich in den letzten Tagen sehr ausführlich mit Excel vergnügt. Ich kann jedem der mit einem Office Programm in Berührung kommt nur LateBinding empfehlen da man da immer Versionsunabhängig ist, sofern man Funktionen nutzt die von allen angezielten Versionen supported werden.

Nun aber zum Thema, ich selbst verwende Office 2007 Beta und bei der Version wird Excel nicht korrekt geschlossen wenn vor dem Close und dem ReleaseComObject eine Exception geschmissen wird.

Vielleicht ist dass ja mal ein Ansatz, ansonsten wenn der Code keine Exception auslöst, schließt sich Excel normal, das kann ich von Version 2000, 2003 und 2007 sagen.

S
1.047 Beiträge seit 2005
vor 17 Jahren

Ich habe vor 2 Jahren mal ein COM-Addin für Word und Excel geschrieben und hatte nur am Anfang Probleme mit nicht wirklich geschlossenen Prozessen.

Nach ein wenig Nachforschung fand ich dann den Hinweis mit Marshal.ReleaseComObject, und seitdem hat ich das Problem nie wieder.

Auf irgendeiner Seite laß ich dann, dass man wirklich jedes Objekt was man direkt oder indirekt nutzt wieder freigeben soll... vielleicht macht ihr genau das nicht?

Direkt heißt dabei z.b.

Word.Application app = new Word.Application();

Indirekt wäre bei

Word.Document doc = app.Documents.Add(...);

das Documents Objekt.

Besser wäre also

Word.Documents docs = app.Documents;
Word.Document doc = docs.Add(...);

Dabei halt immer die Resourcen der Objekte wieder freigeben.
Ich fahr damit seht gut.

Zudem sind mir häufig schlechte Addins untergekommen die selbst wohl nicht ganz sauber programmiert sind und z.b. Word daran hintern die normal.dot am Ende ordentlich zu speichern... (gerade erst wieder durch Acrobat 7.0.0 gehabt, Update auf 7.0.5 hats behoben).

Den Prozess abzuschießen halte ich nicht für eine saubere Lösung. Aber müßt ihr selbst wissen ob ihr das verantworten könnt. Man weiß ja nie ob nicht doch mal ein wichtiges Dokument mit abgeschossen wird.

Vielleicht könnte mir ja jemand beiläufig erklären, wofür das gemacht wird:

Marshal.ReleaseComObject(excelWorksheet);  
Marshal.ReleaseComObject(excelWorkbook);  
Marshal.ReleaseComObject(excelApp);  

Allein durch diese Frage könnt ich dir fast sagen warum dein Programm Probleme hat Excel richtig zu schließen...

Wenn du Objekte von Excel oder Word benutzt, dann sind das COM-Objekte. Diese werden nicht durch den Garbage Collector verwaltet und müßen selbst frei gegeben werden. Das macht man mit der Methode Marshal.ReleaseComObject. Deien explizieten Aufrufe vom GC nutzen also nichts.

Gibst du die Objekte nicht frei wirst du höchstwahrscheinlich einen noch hängenden Prozess haben.

U
195 Beiträge seit 2006
vor 17 Jahren

Also, ersmal vielen Dank für deine Erklärung sheitman. Meine "Beendungs-Prozedur" von Excel sieht nun folgender Maßen aus:


//Excel schliessen
                excelWorkbook.Close(false,missing,missing);
                excelApp.Application.Quit();
                excelApp.Quit();

                //Variablen nullen
                /*excelApp = null;
                excelSheets = null;
                excelWorkbook = null;
                excelWorksheet = null;*/

                // --- COM Objekte wieder freigeben
                Marshal.ReleaseComObject(excelSheets);
                Marshal.ReleaseComObject(excelWorksheet);
                Marshal.ReleaseComObject(excelWorkbook);
                Marshal.ReleaseComObject(excelApp);

Jetzt sieht es folgender Maßen aus. Der Excel Prozess bleibt solange aktiv (also im TaskManager sichtbar) bis ich mein Programm BEENDE. (Das Programm lief in VS). Also Excel wird erst geschlossen, wenn ich mein Programm schliesse. Weiß jemand vielleicht warum?

Muss ich vielleicht auch meine ganzen Ranges (mit denen ich die Excel Zellen anspreche) nullen oder freigeben? Sind ja an sich ganz normale Variablen oder sind es auch solche COM Objekte?

3.728 Beiträge seit 2005
vor 17 Jahren
Ranges

Ja das sind auch COM-Objekte. Die solltest Du auch freigeben, wenn sie klassenweit deklariert sind.

Ich bleibe dabei. Wenn sich Excel nicht richtig schließt, hat man was falsch gemacht.

U
195 Beiträge seit 2006
vor 17 Jahren

Puuh, ey ich hab voll viele Ranges in meinem Programm (sind auch extrem viele verschiedene Daten, die mein Programm an Excel schickt)....So 50 -60 Ranges dürften das sein....glaub da wärs einfacher, den Prozess einfach abzuknallen^^

//edit:

Bin das Prog grad nochma durchgegange und hab mir selbst im Arsch getreten...Ich voll Idiot hab bei vielen Sachen jedes Mal ne neue Range Variable erstellt, wobei ich die alte hätte nutzen können...hab jetzt so 10 mal mehr Ranges als ich bräuchte^^....Muss ich ma wenn ich Zeit hab verbessern....

S
1.047 Beiträge seit 2005
vor 17 Jahren

Nun aber zum Thema, ich selbst verwende Office 2007 Beta und bei der Version wird Excel nicht korrekt geschlossen wenn vor dem Close und dem ReleaseComObject eine Exception geschmissen wird.

Vielleicht ist dass ja mal ein Ansatz, ansonsten wenn der Code keine Exception auslöst, schließt sich Excel normal, das kann ich von Version 2000, 2003 und 2007 sagen.

würde ich übrigens fast auch meine hand für ins feuer legen das es hier am fehlenden Marshal.ReleaseComObject liegt...

hast du alles was du mit excel machst in einen try... catch... finally bzw try... finally ... eingebetten? im finally müßte dann das Marshall.ReleaseComObject rein...

würde also so aussehen


//deklaration der variablen
Word.Documents oDocs = null;
Word.Document oDoc = null;
try {
    oDocs = oWord.Documents;
    oDoc = oDocs.Add(...);
    ...
} catch (SomeException e) {
    ...
} finally {
    if(oDocs!=null) {
        Marshall.ReleaseComObject(oDocs);
    }
    if(oDoc!=null) {
        Marshall.ReleaseComObject(oDoc);
    }
}

wobei es sich schon fast lohnt den ReleaseComObject - code in eine neue methode auszulagern, der auch auf null vorher überprüft^^

jedenfalls ne menge schreibarbeit... aber damit hab ich jedenfalls nie probleme... solange mir kein anderes addin mein word zerschießt^^

Muss ich vielleicht auch meine ganzen Ranges (mit denen ich die Excel Zellen anspreche) nullen oder freigeben? Sind ja an sich ganz normale Variablen oder sind es auch solche COM Objekte?

jedes objekt einer klasse aus dem word, excel oder office namespace dürfte i.d.r. ein com object sein...

S
64 Beiträge seit 2006
vor 17 Jahren

Hi , ich war an dem gleichen Problem ich hätte da nur eine Andere Lösungsart ( ich hab aber von oben gespickt 😁 ) aber die PInvokes haben mir nicht so gefallen also :



Excel.Application xlApp = new Excel.Application();
xlApp.Caption = xlGuid;
//In meinem Programm ist es so dass man das Fenster nicht sehn muss
xlApp.Visible = false;

//Workbook und Worksheet öffnen und sachen damit machen
           
//Hier muss das Fenster geöffnet werden sonst kann man es nicht Identifizieren, aber hald nur Minimiert so merkt nicht ( bzw. kaum )
xlApp.WindowState = Excel.XlWindowState.xlMinimized;
xlApp.Visible = true;

foreach (System.Diagnostics.Process procI in System.Diagnostics.Process.GetProcessesByName("EXCEL")){
      if (procI.MainWindowTitle.IndexOf(xlGuid) != -1) {
                    procI.CloseMainWindow();
                    procI.Refresh();
                    procI.Kill();
       }
}


So spart man sich den PInvoke

lG

Sirox

S
1.047 Beiträge seit 2005
vor 17 Jahren

wie oben schon geschrieben war ists nicht besonders gut einfach so den prozess zu killn.letzlich verdeckt man damit nur das man selbst das problem nicht anders in den griff bekommen hat.

falsl du mal ein com-addin entwickelst stehst du eh wieder vor dem selben problem. und da kannst du wirklich nicht einfach den prozess abschießen... und unsaubere addins sind oft das quell so manch einen übels^^

D
386 Beiträge seit 2007
vor 17 Jahren

Original von Underscare
Also ich kann dieses Problem nur bestätigen. Nutze Excel 2003 und greife über PIA's auf Excel zu.

Hier mal die Code-Stelle, an der ich Excel schliesse:

  
if (chkShowExcel.Checked)  
            {  
                excelApp.Visible = true;  
            }  
            else  
            {  
                //Excel schliessen  
                excelWorkbook.Close(false,missing,missing);  
                excelApp.Application.Quit();  
                excelApp.Quit();  
  
                //Variablen nullen  
                excelApp = null;  
                excelSheets = null;  
                excelWorkbook = null;  
                excelWorksheet = null;  
  
                //Speicher aufräumen lassen (Muss nicht gemacht werden, aber doppelt hällt bekanntlich besser ;) )  
                GC.Collect();  
                GC.WaitForPendingFinalizers();  
            }   
  

Offtopic, aber: Lass die Finger vom GarbageCollector. Ich wette jede Menge Bier darauf, dass dieser Aufruf nicht besser haelt, sondern Unfug ist und nicht das macht was du willst..

Edit: Quoting repariert..

Pound for pound, plutonium is about as toxic as caffeine when eaten.

R
39 Beiträge seit 2006
vor 17 Jahren

hi,

ich habe mich auch eine zeitlang mit diesem problem beschäftigt und bin zu dem schluss gekommen das es ein garbage-collector problem ist.

wenn man extrem sauber und garbage collector "freundlich" programmiert so das er
alle verwendeten variablen problemlos löschen kann, geht auch excel zu. vergisst man aber eine variable in der funktion auf null zu setzten oder noch schlimmer ein dipose aufruf eines erstellten objektes, geht excel erst beim beenden des programmes zu. 😦

anbei ein kleines beispiel progi was bei mir excel wieder zumacht. setzt man aber eine von den variablen am ende nicht null geht excel nicht zu.

            
            Excel.ApplicationClass app = null;
            Excel.Workbook workBook = null;
            Excel.Worksheet workSheet = null;
            Excel.Range range = null;


            app = new Excel.ApplicationClass();
            // create the workbook object by opening the excel file.
            workBook = app.Workbooks.Open(@"test.xls",
                                                     0,
                                                     true,
                                                     5,
                                                     "",
                                                     "",
                                                     true,
                                                     Excel.XlPlatform.xlWindows,
                                                     "\t",
                                                     false,
                                                     false,
                                                     0,
                                                     true, 
                                                     Missing.Value,
                                                     Missing.Value
                                                     );

            if (null != workBook.ActiveSheet)
            {
                workSheet = (Excel.Worksheet)workBook.ActiveSheet;
                range = (Excel.Range)workSheet.Cells[1, 1];
            }

            workBook.Close(false, Missing.Value, Missing.Value);

            app.Application.Quit();
            app.Quit();

            Marshal.ReleaseComObject(range);
            Marshal.ReleaseComObject(workSheet);
            Marshal.ReleaseComObject(workBook);
            Marshal.ReleaseComObject(app);
   
            range = null;
            workSheet = null;
            workBook = null;
            app = null;
            GC.Collect();
            MessageBox.Show("done");
R
39 Beiträge seit 2006
vor 17 Jahren

Nachsatz:

als ich meine function dazu bringen wollte excel nach beendigung wierder zu schließen bin ich übrigens an der function xdoc.CreateElement gescheitert.
was auch wieder auf den gc deutet!

4.221 Beiträge seit 2005
vor 17 Jahren

ReleaseComObject liefert doch einen int zurück welcher anzeigt wie oft das Objekt noch referenziert ist...

Wenn ein call von ReleaseComObject einen Wert > 0 zurückliefert, dann ist eine Instanz (Com-mässig) nicht freigegeben... ergo kann Excel nicht geschlossen werden.

Nachtrag:

Seit Version 2.0 bietet sich hierführ an:

FinalReleaseComObject

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

R
39 Beiträge seit 2006
vor 17 Jahren

mhmmm ich würd aber gerne mal wissen wieso er in meinem beispiel bei

Marshal.ReleaseComObject(workSheet) keine null zurück gibt.

ich sehe da keine referenz ???

4.221 Beiträge seit 2005
vor 17 Jahren

Original von rokohl
ich sehe da keine referenz ???


if (null != workBook.ActiveSheet)  //das erste Marshalling
            {
                workSheet = (Excel.Worksheet)workBook.ActiveSheet; //das zweite Marshalling

Somit zählt er vermutlich auf 2 rauf...

Und du releast nur 1

probier es mal so:


workSheet = (Excel.Worksheet)workBook.ActiveSheet; //das zweite 
if (workSheet!=null)
.
..

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

R
39 Beiträge seit 2006
vor 17 Jahren

du hast recht. das zählt er als ref.
mhm...aber ich verstehe das immer noch nicht 100%ig.
ich hatte den fall das es an einem xdoc.CreateElement aufruf lag den ich zwischen den excel befehlen verwendet hatte. ohne ihn lief es - mit ihm hat er excel nicht zu gemacht. obwohl da nix von excel verwendet wurde sondern nur xml krams.

desweiteren is an meinem beispiel interessant das es excel auch zu macht wenn man alles am ende auf null setzt. heißt das das ReleaseComObject automatisch aufgerufen wird? das würde ja bedeuten das man ReleaseComObject garnicht aufrufen muss.

naja egal, aber komisch ist das schon...

danke nochmal

27 Beiträge seit 2006
vor 16 Jahren

*aufweck*

Hab auch ein Problem mit dem Schließen von Excel.

Meine Methode sieht so aus (bitte nicht den Sinn hinterfragen...):

private void ReSaveExcelFile(string filename)
        {
            Excel.Application excelApp = new Microsoft.Office.Interop.Excel.ApplicationClass();
            Excel.Workbook wb = null;
            try
            {
                wb = excelApp.Workbooks.Open(filename, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
                     Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
                     Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
                wb.SaveAs(filename,Excel.XlFileFormat.xlExcel7, 
                    Type.Missing,Type.Missing,Type.Missing,Type.Missing, Excel.XlSaveAsAccessMode.xlNoChange,
                    Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Fehler beim Speichern der Datei '" + filename + "': " + ex.Message,
                        this.messageBoxCaption, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                wb.Close(Type.Missing, Type.Missing, Type.Missing);
                excelApp.Application.Quit();
                excelApp.Quit();
                System.Runtime.InteropServices.Marshal.ReleaseComObject(excelApp);
                System.Runtime.InteropServices.Marshal.ReleaseComObject(wb);
                wb = null;
                excelApp = null;
            }

        }

Obwohl ich mMn alles richtig geschlossen und freigegeben habe, bleibt der Excel-Prozess bis ich meine Anwendung geschlossen habe offen.

Warum?

thx for hints

and that's the bottom line: ____________________

183 Beiträge seit 2004
vor 16 Jahren

Moin,

Ursache:


wb = excelApp.Workbooks.Open([...]);   // Marshalled Workbooks und zählt den Referenzzähler für Workbooks hoch
excelApp.Application.Quit();  // Marshalled Application und zählt den Referenzzähler dafür hoch

also lieber so


Excel.Workbooks wbs = excelApp.Workbooks;
wb = wbs.Open([...]);

Excel.Application app = excelApp.Application;
app.Quit();

System.Runtime.InteropServices.Marshal.ReleaseComObject(wbs);
System.Runtime.InteropServices.Marshal.ReleaseComObject(app);

wobei


excelApp.Application == excelApp

👍

Warum nutzt du nicht System.IO.File.Copy ?(

So einfach wie möglich, aber nicht einfacher. [Albert Einstein]

take a look at
* baer-torsten.de
* codinghints

27 Beiträge seit 2006
vor 16 Jahren

Original von él toro
Warum nutzt du nicht System.IO.File.Copy ?(

Ich hab doch gesagt nicht hinterfragen 😉
Die Funktion soll eine Excel-Datei unter einer anderen Excel-Version speichern, da ich von einer anderen Anwendung eine Datei im Excel 3.0-Format erhalte und das zur Weiterverarbeitung nicht geeignet ist...

@tipp:
funktioniert, danke!

and that's the bottom line: ____________________

183 Beiträge seit 2004
vor 16 Jahren

Bitte 😁

So einfach wie möglich, aber nicht einfacher. [Albert Einstein]

take a look at
* baer-torsten.de
* codinghints

R
56 Beiträge seit 2009
vor 14 Jahren

Hallo Leute.

Jetzt muss ich einen alten Beitrag wieder aufwärmen, weils bei mir einfach nicht hinhaut.
Der Prozess "Excel.exe" wird einfach nicht beendet.

Weis jemand an was das liegen könnte? Benutze Vista Enterprise und Office 2007.

Folgend noch mein code:


private void button1_Click(object sender, EventArgs e)
{
    object missing = Type.Missing;
    string PosX, PosY;
    int i;

    //.xml-File mit Excel öffnen und Daten auslesen um die ovl Dateien zu erzeugen
    Excel.Application excelApp = new Excel.Application();
    Excel.Workbook workbook = excelApp.Workbooks.Open(Dateipfad() + @"\File.xml", missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing);
    Excel.Worksheet worksheet = (Excel.Worksheet)workbook.Worksheets["wks-Name"];

    excelApp.Visible = true;

    //Anzahl der Zeilen ermitteln
    string beginCell = "A" + worksheet.Rows.Count;
    string endCell = "AA" + worksheet.Rows.Count;

    int row = worksheet.get_Range(beginCell, endCell).get_End(Excel.XlDirection.xlUp).Row;

    for (i = 2; i <= row; i++)
    {
        //Daten aus Excelfile ermitteln
        Excel.Range Xrng = worksheet.get_Range("A"+i, "F"+i);
        Excel.Range Yrng = worksheet.get_Range("P"+i, "S"+i);

        PosX = (string)Xrng.get_Value(missing);
        PosY = (string)Yrng.get_Value(missing);

        //Textdatei erstellen, Daten eintragen und Text speichern
        StreamWriter Writer = new StreamWriter(Dateipfad() + ".txt", false, Encoding.Default);
                
        //Daten für Markierung eintragen
        Writer.WriteLine("TextTextText");

        Writer.Close();
    }

    //Excel schließen
    workbook.Close(false, missing, missing);
    excelApp.Application.Quit();
    excelApp.Quit();

    //COM Objekte freigeben um EXCEL.exe zu schließen
    Marshal.FinalReleaseComObject(worksheet);
    Marshal.FinalReleaseComObject(workbook);
    Marshal.FinalReleaseComObject(excelApp);

    //Variablen auf Null setzen
    PosX = null;
    PosY = null;
    worksheet = null;
    workbook = null;
    excelApp = null;
}

Gruß
Red_Dragon69

http://ifail.de - Jedem geht's beschissen. 😁

4.221 Beiträge seit 2005
vor 14 Jahren

el toro hat in seinem Beitrag aufgezeigt wo Fehler gemacht wurden.

Du machst genau dieselben Fehler... findest allerdings diesen Thread....

Hast Du den Beitrag auch mal ernsthaft durchgelesen ??? eher nicht, sonst hättest Du den Fehler ja gefunden ...

--> Lies nochmals alles durch ... bin überzeugt dass Du den Fehler selber findest.

Gruss
Programmierhans

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

T
34 Beiträge seit 2009
vor 14 Jahren

Also ich schliess mich mal Rainbird an. Hab alles sauber zugemacht und Excel wird geschlossen.

gute und hilfreiche Diskussion hier.

G
22 Beiträge seit 2009
vor 14 Jahren

Kurze Ergänzung für die Suchmaschinen:

Das Schließen von offenen Word- und Visio-Dateien funktioniert genauso... 🙂

Super Thread. Ist der nicht schon was für die FAQs? 👍

Gruß Gabe

S
1 Beiträge seit 2018
vor 5 Jahren

Egal wie alt dieser Beitrag ist. Genau das freigeben der COM Objekte hat mir bei diesem Problem geholfen. Dabei gebe ich mittlerweile alle Objekte direkt wieder frei, egal ob in For Schleifen oder sonst wo. Wenn diese nicht mehr benötigt werden werden sie freigegeben.

Vielen Dank 👍 😁

Hinweis von Abt vor 5 Jahren

Keine Full Quotes
[Hinweis] Wie poste ich richtig?

174 Beiträge seit 2009
vor 4 Jahren

Hallo,

ich habe mich nun auch länger mit dem Thema beschäftigen müssen, aber leider komme ich an einem Punkt nicht weiter 8o


    try
    {
        // First Contact: Excel Prozess initialisieren
        oExcel = new Excel.Application();
        //oExcel.Visible = false;
        oExcel.ScreenUpdating = true;

        // Excel Datei anlegen: Workbook
        oExcelWorkbooks = oExcel.Workbooks;
        oExcelWorkbook = oExcelWorkbooks.Add(System.Reflection.Missing.Value);
        oExcelWorkSheet = oExcelWorkbook.ActiveSheet;
        oExcelWorkSheet.Name = x_dateiname.ToString().Trim();

        // Überschriften eingeben 
        oExcelWorkSheet.Cells[1, 1] = "test";

        // Excel Datei abspeichern 
        oExcelWorkbook.Close(true, auswertung_speichern_unter.FileName, System.Reflection.Missing.Value);

    }
    catch (Exception ex)
    {
        Fehlermeldung.ErrorMessage(ex, "( --> Datei geöffnet ???   <--  )");
        vorgang_fortsetzen = false;
    }
    finally
    {
        // Excel beenden
        if (oExcel != null)
        {
            oExcel.Quit();
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(oExcelWorkSheet);
            oExcelWorkSheet = null;
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(oExcelWorkbook);
            oExcelWorkbook = null;
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(oExcelWorkbooks);
            oExcelWorkbooks = null;
            System.Runtime.InteropServices.Marshal.FinalRelease(oExcel);
            oExcel = null;
        }
    }

kommentiere ich die Zeile "oExcelWorkSheet.Cells[1, 1] = "test";" aus, funktioniert alles so wie es soll, u. es wird Excel im TaskManager geschlossen

da es wohl für Cells kein Comobjekt gibt (zumindest habe ich keins gefunden...)
habe ich es dann mit Hilfe von Range versucht :


        Excel.Range x_celle = (Excel.Range)oExcelWorkSheet.Cells[1, 1];
        x_celle.Value2 = "test";
        System.Runtime.InteropServices.Marshal.FinalReleaseComObject(x_celle);

aber auch dann wird Excel nicht mehr im TaskManager geschlossen 😜

Wenn ich die entsprechenden Release-Befehle im Direktfenster eingebe, bekomme ich immer "0" zurück, was nach den obigen Ausführungen ja bedeutet, das alle Objekte geschlossen sind ...

Was sehe ich hier nicht / mache ich immer noch falsch ?

Bin für jede Hilfe dankbar ...

MfG ChrisProrg