Excel richtig schließen

  • VB.NET

Es gibt 23 Antworten in diesem Thema. Der letzte Beitrag () ist von Thisoft.

    Excel richtig schließen

    Hallo zusammen,

    bei meinem folgendem Code wird der Excel Prozess in der "Private Sub Excel_Passwort_oeffnen()" nicht nach der Ausführung geschlossen.
    Nach mehrmaligen ausführen der Funktion fragt Excel das Passwort ab :|
    Erst nach beenden des Programmes verschwindet der Prozess aus dem Taskmanager.
    Er soll aber nach beenden der Funktion sofort geschlossen werden.

    Danke für eure Hilfe

    Visual Basic-Quellcode

    1. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    2. Excel_Passwort_oeffnen()
    3. End Sub
    4. Private Sub Excel_Passwort_oeffnen()
    5. Try
    6. Dim xlApp As New Excel.Application
    7. Dim xlMappe = xlApp.Workbooks.Open(Application.StartupPath & "\Prodkon.xlsx", Password:="Passwort")
    8. xlApp.Visible = False
    9. xlApp.DisplayAlerts = False
    10. LoadExcelFile("Prodkon.xlsx", "Prod-Kon-Liste")
    11. xlMappe.Saved = False
    12. xlMappe.Close()
    13. xlApp.Quit()
    14. xlApp = Nothing
    15. GC.Collect()
    16. GC.WaitForFullGCComplete()
    17. Catch ex As Exception
    18. MessageBox.Show(ex.Message.ToString)
    19. End Try
    20. End Sub
    21. Private Function LoadExcelFile(ByVal path As String, ByVal table As String) As DataSet
    22. Try
    23. Dim connString As String
    24. If path.ToLower.EndsWith(".xlsx") Then
    25. connString = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=" & path & "; Extended Properties=Excel 12.0;"
    26. Else
    27. connString = "provider=Microsoft.Jet.OLEDB.4.0; data source=" & path & "; Extended Properties=Excel 8.0;"
    28. End If
    29. Using myConnection = New OleDb.OleDbConnection(connString)
    30. Dim myCommand As OleDb.OleDbDataAdapter
    31. myCommand = New OleDb.OleDbDataAdapter("select * from [" & table & "$] WHERE Logik LIKE 'ja'", myConnection)
    32. myCommand.TableMappings.Add("Table", "TestTable")
    33. dtSet = New DataSet
    34. myCommand.Fill(dtSet)
    35. Me.DataGridView1.DataSource = dtSet.Tables(0)
    36. myConnection.Close()
    37. End Using
    38. Catch ex As Exception
    39. MessageBox.Show(ex.Message.ToString)
    40. End Try
    41. Return dtSet
    42. End Function

    majachen99 schrieb:

    sofort geschlossen werden.
    Teste mal dies:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Dim xlApp As New Excel.Application
    2. Dim path = "c:\temp\test.xlsx"
    3. Dim xlMappe = xlApp.Workbooks.Open(path) ', Password:="Passwort")
    4. xlApp.Visible = False
    5. xlApp.DisplayAlerts = False
    6. LoadExcelFile(path, "xxx")
    7. xlMappe.Saved = True
    8. xlMappe.Close()
    9. xlApp.Quit()
    10. System.Runtime.InteropServices.Marshal.ReleaseComObject(xlMappe)
    11. System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp)
    12. GC.Collect()
    13. GC.WaitForFullGCComplete()
    1. musst Du der Mappe sagen, dass sie gespeichert ist (Du setzt sie auf ungespeichert),
    2. rufe ReleaseComObject() auf.
    Feddich.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hallo,

    ich hänge mich hier mal mit dran da ich schon länger genau das gleiche Problem habe. Jetzt dachte ich, ich hätte endlich die Lösung...

    Aber RelaseComObject() hilft (zumindest bei mir) auch nicht. Ich hab's jetzt auch schon mit FinalReleaseComObject() versucht. Hilft auch nix - der Excel-Process bleibt im Taskmanager bis das Programm beendet wird.

    Gruß Thilo
    Und wenn du es so anhängst?

    VB.NET-Quellcode

    1. Private Sub releaseObject(ByVal obj As Object)
    2. Try
    3. System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
    4. obj = Nothing
    5. Catch ex As Exception
    6. obj = Nothing
    7. Finally
    8. GC.Collect()
    9. End Try
    10. End Sub


    So klappt es zumindest bei mir, das keine Überhänge im Taskmanager zusehen sind.
    Hast du dir das mal mit angeschaut
    setz mal xlApp.Visible = true

    Ggf. ist irgendein Dialog noch da?

    //Edit:

    Hast du schon :
    System.GC.WaitForPendingFinalizers();
    versucht?
    Das ist meine Signatur und sie wird wunderbar sein!

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Mono“ ()

    Also bei sehe ich den Excel Prozess und wie er wieder verschwindet:

    C#-Quellcode

    1. private void button1_Click(object sender, EventArgs e)
    2. {
    3. Excel.Application exc = new Excel.Application();
    4. exc.Visible = false;
    5. Excel.Workbook w = exc.Workbooks.Open("D:\\Test.xlsx", Password:"123",WriteResPassword:"123");
    6. w.Worksheets["Sheet4"].Cells(5, 9).Value = 1299;
    7. LoadExcelFile("D:\\Test.xlsx", "Sheet2");
    8. w.Close(Excel.XlSaveAction.xlSaveChanges);
    9. exc.Quit();
    10. exc = null;
    11. System.GC.Collect();
    12. }
    13. private void LoadExcelFile(string path, string table)
    14. {
    15. DataSet dtSet = new DataSet();
    16. string connString = null;
    17. if (path.ToLower().EndsWith(".xlsx"))
    18. {
    19. connString = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=" + path + "; Extended Properties=Excel 12.0;";
    20. }
    21. else
    22. {
    23. connString = "provider=Microsoft.Jet.OLEDB.4.0; data source=" + path + "; Extended Properties=Excel 8.0;";
    24. }
    25. using (OleDbConnection myConnection = new OleDbConnection(connString))
    26. {
    27. OleDbDataAdapter myCommand = new OleDbDataAdapter("select * from [" + table + "$]", myConnection);
    28. myCommand.Fill(dtSet);
    29. this.dataGridView1.DataSource = dtSet.Tables[0];
    30. myConnection.Close();
    31. }
    32. }


    Ich frag mich immer warum soviele Probleme damit berichten..ich kann das nie nachvollziehen


    Vielleicht liegt es daran, dass du beim Close nicht angibst ob die Datei gespeichert werden soll.
    w.Close(Excel.XlSaveAction.xlDoNotSaveChanges);
    oder
    w.Close(Excel.XlSaveAction.xlSaveChanges);
    Das ist meine Signatur und sie wird wunderbar sein!

    Mono schrieb:

    ob die Datei gespeichert werden soll
    Jou. Deswegen hab ich oben das Save-Flag explizit auf True gesetzt:

    RodFromGermany schrieb:

    VB.NET-Quellcode

    1. xlMappe.Saved = True

    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Scriptum schrieb:

    Mir schwirrt da etwas im Kopf rum mit "proc.kill", weiß jedoch nicht ob sowas überhaupt geht...
    ja, das geht - einfach mal das Tutorial angugge.
    proc.Kill() ist halt sone Sache, ob man Excel wirklich killen will. Evtl. hatte es der User ja bereits offen - da wird er sich bedanken für ein Killing.
    Wie im Tut erwähnt: Wo es möglich ist, fährt man wohl am besten mit einer OpenSource-non-Com-InterOp-Dll. Aber das ist auch nicht immer möglich, denn die OpenSource laufen den sich ändernden xls-Format-Spezifikationen immer bischen hinterher.

    ErfinderDesRades schrieb:

    proc.Kill()
    Jou.
    @Scriptum Allerdings kann es da Schwierigkeiten geben, wenn da mehrere Instanzen offen sind.
    Nach McMurphy wird da stets die falsche Instanz gekillt.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Also, bei mir hat alles nix geholfen:
    -Dialoge etc. waren keine im Excel offen
    -System.GC.WaitForPendingFinalizers() hab ich ohne Erfolg versucht
    -w.Close(Excel.XlSaveAction.xlDoNotSaveChanges) hat auch keine Änderung gebracht

    Ich hab jetzt auch den rabiaten Weg über Kill() gewählt:

    VB.NET-Quellcode

    1. Private Sub Kill_ExcelInstanz()
    2. Dim Excproclist As Process() = Process.GetProcessesByName("Excel")
    3. For i = 0 To UBound(Excproclist)
    4. If Excproclist(i).MainWindowTitle = "" Then Excproclist(i).Kill()
    5. Next
    6. End Sub


    Über die Auswahl nach MainWindowTitle kann man hier eigentlich ganz gut steuern welchen Prozess genau man killen möchte.

    Gruß Thilo
    Hallo zusammen,

    erstmal vielen Dank für eure Hilfe.
    Bei mir muss das Programm auf verschiedenen Rechnern laufen. Ab Win 7 und Office 2010 , jeweils in 32 und 64 bit.

    Die bei mir aktuell am besten laufende Version ist: siehe unten im Spoiler.
    Da wird der jeweilige Prozess im Taskmanager geschlossen. :thumbsup:
    Wenn ich aber eine anderes Excel auf habe bleibe ich bei der Passwort - Abfrage von Excel hängen ?(

    Die Excel Prozesse generell killen will ich nicht. Da gebe ich ErfinderDesRades recht.

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    2. Excel_Passwort_oeffnen()
    3. End Sub
    4. Private Sub Excel_Passwort_oeffnen()
    5. Try
    6. Dim xlApp As New Excel.Application
    7. Dim xlMappe = xlApp.Workbooks.Open(Application.StartupPath & "\Prodkon.xlsx", Password:="Passwort", WriteResPassword:="Passwort")
    8. xlApp.Visible = True
    9. xlApp.DisplayAlerts = False
    10. LoadExcelFile("Prodkon.xlsx", "Prod-Kon-Liste")
    11. 'MessageBox.Show(CDbl(xlMappe.Worksheets("Kalkulation").Cells(16, 2).Value))
    12. xlMappe.Saved = False
    13. xlMappe.Close(Excel.XlSaveAction.xlSaveChanges)
    14. xlApp.Quit()
    15. xlApp = Nothing
    16. System.GC.Collect()
    17. System.GC.WaitForFullGCComplete()
    18. Kill_ExcelInstanz()
    19. Catch ex As Exception
    20. MessageBox.Show(ex.Message.ToString)
    21. End Try
    22. End Sub
    23. Private Function LoadExcelFile(ByVal path As String, ByVal table As String) As DataSet
    24. Try
    25. Dim connString As String
    26. If path.ToLower.EndsWith(".xlsx") Then
    27. connString = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=" & path & "; Extended Properties=Excel 12.0;" ' Xml; HDR=Yes; IMEX=1;"
    28. Else
    29. connString = "provider=Microsoft.Jet.OLEDB.4.0; data source=" & path & "; Extended Properties=Excel 8.0;"
    30. End If
    31. Using myConnection = New OleDb.OleDbConnection(connString)
    32. Dim myCommand As OleDb.OleDbDataAdapter
    33. myCommand = New OleDb.OleDbDataAdapter("select * from [" & table & "$] WHERE Logik LIKE 'ja'", myConnection)
    34. myCommand.TableMappings.Add("Table", "TestTable")
    35. dtSet = New DataSet
    36. myCommand.Fill(dtSet)
    37. 'MessageBox.Show((dtSet.Tables(0).Rows(0).Item(3).ToString))
    38. 'MessageBox.Show((dtSet.Tables(0).Rows.Count.ToString & " x ja "))
    39. Me.DataGridView1.DataSource = dtSet.Tables(0)
    40. myConnection.Close()
    41. End Using
    42. Catch ex As Exception
    43. MessageBox.Show(ex.Message.ToString)
    44. End Try
    45. Return dtSet
    46. End Function
    47. Private Sub Kill_ExcelInstanz()
    48. Dim Excproclist As Process() = Process.GetProcessesByName("Excel")
    49. For i = 0 To UBound(Excproclist)
    50. If Excproclist(i).MainWindowTitle = "" Then Excproclist(i).Kill()
    51. Next
    52. End Sub

    majachen99 schrieb:

    VB.NET-Quellcode

    1. xlMappe.Saved = False
    Machst Du

    VB.NET-Quellcode

    1. xlMappe.Saved = True

    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    egal welche Kombination ich nehme. Sobald ein weiteres Excel offen ist will er im Dialog das Passwort für die Excel-Datei haben. X(




    Diese Datei muss aber mit Passwort gesichert sein. Ohne Passwort komme ich ja über OleDb ran.
    Aber ich muss ja leider Excel erstmal über diesen Weg öffnen, dann das Dataset im einen Rutsch füllen und dann wieder schließen, oder ? Performance ist wichtig. ?(

    Danke auch

    Spoiler anzeigen

    VB.NET-Quellcode

    1. xlMappe.Saved = True
    2. 'xlMappe.Close(Excel.XlSaveAction.xlSaveChanges)
    3. xlApp.Quit()
    4. xlApp = Nothing
    5. System.GC.Collect()
    6. System.GC.WaitForFullGCComplete()
    7. Kill_ExcelInstanz()
    8. System.Runtime.InteropServices.Marshal.ReleaseComObject(xlMappe)
    9. 'System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp)