Domanda

I am using the win32com (Python 2.7 (Anaconda) in LiClipse) to start separate instances of excel...

class ExcelDocument(object):
    """Excel class
    """
    def __init__(self, xlDocIn, make_visible=False):
        """Open spreadsheet"""
        self.excelApp = DispatchEx('Excel.Application')

I then do bits and bobs to the excel document (using MS Office 2013), including opening another document with DispatchEx...

objExcel1 = ExcelDocument(PATH_TABLE,False)
objExcel1.update_sheets()
...
objExcel2 = ExcelDocument(PATH_BACKG, False)

Trying to assign a second ExceLDocument class will crash the script.

If I change init to

def __init__(self, xlDocIn, make_visible=False):
        """Open spreadsheet"""
        try:
            self.excelApp = GetActiveObject('Excel.Application')
        except:
            self.excelApp = DispatchEx('Excel.Application')

the script runs fine.

If i have an excel file open when I run the script either a. the script will crash upon editing the open file. b. the open excel file will close when these lines of code are executed...

def close(self):
        """Close spreadsheet resources"""
        self.excelApp.DisplayAlerts = True
        self.workbook.Saved = 0
        self.workbook.Close(SaveChanges=0)
        self.excelApp.Visible = 0

Is there a reason I cannot call DispatchEx the second time, as my script should run in the background and not interrupt the any open excel files?

È stato utile?

Soluzione

You should design your script assuming there can only be one instance of Excel running, although it can contain multiple workbooks. If you use GetObject (instead of GetActiveObject) then win32com will return a handle to the existing app if one exists, or start the app if it doesn't. So you won't need the if/else.

Also what this means in terms of design is that you should have a way of tracking which workbooks get opened, and close only those, so that the final state of the Excel application is the same as when you started script. So you would have one instance of ExcelDocument per workbook, each using GetObject, and each one closing the workbook that it represents. Before you create the first ExcelDocument, save GetActiveObject so your script knows if it should close the app on exit.

Basically:

activeXlApp = win32com.client.GetActiveObject('Excel.Application') 

objExcel1 = ExcelDocument(PATH_TABLE,False) # uses GetObject()
objExcel1.update_sheets()
...
objExcel2 = ExcelDocument(PATH_BACKG, False)

if activeXlApp is not None: 
    activeXlApp.Close()
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top