Geöffnete Datei schließen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
DMD-OS
User
Beiträge: 165
Registriert: Freitag 28. Dezember 2018, 13:52

hi
wie kann man eine von hand (per doppelclick) geöffnete excel-datei wieder schließen, bevor man etwas darin speichert.

Code: Alles auswählen

import os
import win32com.client as win32

path_main = os.getcwd()
input_folder = os.path.join(path_main, "import")
excel_file = os.path.join(input_folder, "Testdatei.xlsx")

excel = win32.gencache.EnsureDispatch('Excel.Application')
excel.Workbooks.Open(Filename=excel_file)
if excel.Visible is True:
    excel.Visible = False
    # del excel
    print('Closed')
else:
    excel.Visible = True
    print('Opened')
der code funktioniert zwar, solange man die betreffende datei nicht von hand (doppelclick) oder per os.startfile(excel_file) öffnet.
kann man per hand oder os.startfile(excel_file) auch irgendwie aus dem code heraus schließen?
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

Wenn Du die Datei per Hand öffnest, mußt Du halt über die COM-Schnittstelle das passende Workbook suchen, wie auch immer Du genau dieses Workbook erkennen willst.

Der `is True` ist schlecht. Lass das doch einfach weg. Nur weil Excel nicht mehr sichtbar ist, ist das göffnete Workbook noch lang nicht geschlossen. Dafür gibt es eine passende Methode.
Zuletzt geändert von Sirius3 am Montag 20. Januar 2020, 16:53, insgesamt 1-mal geändert.
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Was hast du denn genau vor? Du könntest mit subprocess den Task killen, aber ich glaube wenn du uns dein Vorhaben mitteilst findet man eine Lösung die evtl mehr dafür geeignet ist.
DMD-OS
User
Beiträge: 165
Registriert: Freitag 28. Dezember 2018, 13:52

Ich lese eine Excel-Datei ein, die ich als SQL-Datenbank speicher.
Dazu lese ich die Excel-Datei (mit den jeweiligen Sheets) zunächst aus und stelle in einer Tabelle
NAME (Label), MAX. ZEILENANZAHL (Label) und USERZEILE (Entry) eines jeden Sheets in der Datei dar.
Durch darüberfahren mit der Maus über das Entry, wird dann in einer zweiten Tabelle, jeweils der Inhalt des Sheets (mit Zeilennummerierung) gezeigt (naja immer die ersten 15 Zeilen, nicht alles).
Ausserdem kann in das Entry nach Darüberfahren dann eine Zeile (durch Eingabe einer Zahl) angegeben werden, die auch makiert wird.
Ab dieser Zeile soll dann jede nachstehende Zeile als SQL-Datenbank eingelesen werden.
Es wird natürlich nach Festlegung einer sozusagen Headerzeile geprüft, ob diese Zeile als Headerzeile geeignet ist.
Wenn nicht, werden die Zellen der Headerzeile entsprechend farblich makiert und die Excel-Datei geöffnet.
HIER IST DAS PROBLEM, denn wenn man die fehlerhafte Headerzeile richtig stellt und das Programm wieder laufen lässt, bekomme ich eine Fehlermeldung,
da ich die Änderungen bei geöffneter Excel-Datei nicht speichern kann :(
Außerdem will ich generell bei Programmstart, daß alle benötigten Excel-Dateien vorher immer geschlossen werden, bevor es losgeht (auch per Hand geöffnete).
Alles funktiert soweit, nur das VERDAMMTE Schließen nicht :(
Benutzeravatar
sparrow
User
Beiträge: 4538
Registriert: Freitag 17. April 2009, 10:28

Wie liest du denn Excel-Daten ein?
Indem du Excel öffnest? Warum das denn? Das klingt super kompliziert. Es gibt doch genug Tools um in Python direkt Excel-Dateien zu lesen.
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

@DMD-OS: ich verstehe kein Wort, von dem, was Du da mit der Maus und sonstwie machst.
Für mich hört sich das entweder danach an, als ob Du in Excel ein Interaktives Sheet programmieren solltest, oder das ganze mit Python-Bordmitteln irgendwie lösen.
Da wie immer der passende Code fehlt, kann man nur spekulieren, wie Du hier was umgesetzt hast, und wo denn nun konkret das Problem liegen soll, weil scheinbar tut ja schon irgendetwas.

Und wie schon in meinem ersten Post: Excel hat viele Methoden, um die offenen Workbooks zu ermitteln und diese auch zu schließen. Wo ist das Problem, diese zu nutzen?
DMD-OS
User
Beiträge: 165
Registriert: Freitag 28. Dezember 2018, 13:52

Naja, das Problem ist kurzgefasst folgendes:

Code: Alles auswählen

import os
import win32com.client as win32

path_main = os.getcwd()
input_folder = os.path.join(path_main, "import")
excel_file = os.path.join(input_folder, "Testdatei.xlsx")

# Stellvertretend, für eine von Hand (Doppelklick) geöffnete Datei.
# Jetzt ist diese geöffnete Datei immer sichtbar.
# Wie kann man insgesamt alle zum späteren Speichern benötigten Dateien (z.B. per Pfad oder so) finden und TÖTEN, TÖTEN, TÖTEN!
os.startfile(excel_file)  # <-- SICHTBAR (FINDEN UND SCHLIESSEN)

# Danach kann dann hiermit gearbeitet werden :)
excel = win32.gencache.EnsureDispatch('Excel.Application')
excel.Workbooks.Open(Filename=excel_file)
if excel.Visible is True:
    excel.Visible = False
    # del excel
    print('Closed')
else:
    excel.Visible = True
    print('Opened')
Ich hoffe, jetzt ist es verständlicher :)
Benutzeravatar
/me
User
Beiträge: 3561
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

In VBA gibt `Workbooks.Open` als Rückgabe das geöffnete Workbook zurück und ich gehe davon aus, dass das via Python-Schnittstelle nicht anders aussieht. Zum Schließen solltest du dann doch darauf die `Close`-Methode aufrufen können.
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

Verständlich war das von Anfang an, nur Du scheinst die Lösungshinweise nicht weiter zu verfolgen. Wenn Du schon eine Excel.Application hast, dann brauchst Du das os.startfile nicht mehr.
DMD-OS
User
Beiträge: 165
Registriert: Freitag 28. Dezember 2018, 13:52

Richtig, das brauche ich dann nicht mehr. Es ist aber ja auch möglich, eine Excel-Datei nicht nur mit dem Programm zu öffnen oder schließen, sondern (leider) auch mit einem Doppelklick direkt durch den Benutzer.
Wenn das von "Außen" geschieht, hat mein Programm eine trotzdem geöffnete Datei vor sich und kann nicht zum Speichern draufzugreifen :(
Sonst wär ja alles ok, nur der scheiß Benutzer kann wieder mist bauen :)
Die von außerhalb geöffneten will ich gern schließen. Programmintern ist alles tutti.
Benutzeravatar
/me
User
Beiträge: 3561
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

DMD-OS hat geschrieben: Mittwoch 22. Januar 2020, 11:15 Die von außerhalb geöffneten will ich gern schließen. Programmintern ist alles tutti.
Man kann auch auf eine bereits geöffnete Datei zugreifen und diese speichern und schließen. Du kannst die Datei nur nicht ein zweites Mal öffnen. In VBA habe ich das beim Öffnen mal mit folgender Funktion abgefangen:

Code: Alles auswählen

Function OpenExcelFile(FileName) As Workbook
    Dim CurrentWorkbook As Workbook
    
    For Each CurrentWorkbook In Application.Workbooks
        If LCase$(FileName) = LCase$(CurrentWorkbook.Path & "\" & CurrentWorkbook.Name) Then
            ' use existing open file
            Set OpenExcelFile = CurrentWorkbook
            Exit Function
        End If
    Next
    
    Set OpenExcelFile = Workbooks.Open(FileName, UpdateLinks:=0, Editable:=True, AddToMRu:=False)
End Function
Anschließend habe ich dann ein Workbook-Objekt, unabhängig davon ob die Datei bereits geöffnet war oder erst durch `Workbooks.Open` geöffnet wurde.

Ein Schließen aller Excel-Dateien der aktuell laufenden Excel-Anwendung sollte in VBA so gehen (ungetestet):

Code: Alles auswählen

Sub CloseAllExcelFiles()
    Dim CurrentWorkbook As Workbook
    
    For Each CurrentWorkbook In Application.Workbooks
        CurrentWorkbook.Close()
    Next
End Sub
Der Code müsste sich eigentlich in Python umsetzen lassen. `Close` kann man meines Wissens auch noch Parameter mitgeben die angeben, ob man Änderungen ignorieren will und ähnliches.
DMD-OS
User
Beiträge: 165
Registriert: Freitag 28. Dezember 2018, 13:52

ok, das hab ich dann auch schon bei mir drin. Ich frage am anfang ab, ob man die datei öffnen kann:

Code: Alles auswählen

    def check_open_file(self):
        try:
            myfile = open(self.process_file, "r+")
            myfile.close()
            return True
        except Exception:
            return False
Wenn man die nicht öffnen kann gibts ein false, also ist die datei schon geöffnet.
Kann man den 'except' noch genauer abfangen, als nur mit except Exception?
Da fehlt es bei mir auch immer...

Code: Alles auswählen

    def check_open_file(self):
        try:
            myfile = open(self.process_file, "r+")
            myfile.close()
            return True
        except Exception_für_Öffnen_einer_Datei:
            return False
Benutzeravatar
/me
User
Beiträge: 3561
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Nimm mal den try-except-Block raus. Dann solltest du eine entsprechende Fehlermeldung zurückbekommen die du dann auch gezielt abfragen kannst wenn du das try-except wieder reinnimmst.
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

@DMD-OS: das Prüfen ist nicht sehr robust. Warum nutzt Du nicht die COM-Schnittstelle so wie es Dir /me gezeigt hat?
DMD-OS
User
Beiträge: 165
Registriert: Freitag 28. Dezember 2018, 13:52

:)
@ Sirius3: ich kenn mich überhaupt nicht mit VBA code aus und versteh auch ehrlicherweise nicht was die COM-Schnittstelle damit zu tun hat :geek:
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

@DMD-OS: Du sprichst Excel von Python aus über die COM-Schnittstelle an. Das Interface ist das selbe, wie Dir in VBA zur Verfügung steht. Da es keine explizite COM-Dokumentation gibt, mußt Du, wenn Du Dich über die Funktionen informieren möchtest, die Du brauchst, in die VBA-Dokumentation schauen: https://docs.microsoft.com/de-de/office ... .workbooks
Antworten