打开和调度的Excel进程之间的交互,win32com

1 投票
1 回答
2535 浏览
提问于 2025-04-17 23:44

我正在使用win32com(Python 2.7(Anaconda)在LiClipse中)来启动多个Excel实例...

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

然后我对Excel文档进行一些操作(使用MS Office 2013),包括用DispatchEx打开另一个文档...

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

尝试给第二个ExceLDocument类赋值会导致脚本崩溃。

如果我把init改成

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

脚本就能正常运行。

如果我在运行脚本时已经打开了一个Excel文件,要么 a. 脚本在编辑打开的文件时会崩溃。 b. 当执行这些代码行时,打开的Excel文件会关闭...

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

为什么我不能第二次调用DispatchEx呢?因为我的脚本应该在后台运行,不应该干扰任何打开的Excel文件。

1 个回答

2

你在写脚本的时候,应该假设电脑上只能同时打开一个Excel程序,虽然这个程序可以有多个工作簿(就是你打开的文件)。如果你使用 GetObject(而不是 GetActiveObject),那么win32com会帮你找到已经打开的Excel程序,如果没有的话,它会自动启动一个新的。所以你就不需要用if/else来判断了。

这也意味着,在设计上,你需要有办法记录哪些工作簿被打开了,并且只关闭这些工作簿,这样最后Excel的状态就和你开始脚本时是一样的。也就是说,每个工作簿都应该有一个对应的ExcelDocument实例,每个实例都使用 GetObject,并且负责关闭它所代表的工作簿。在你创建第一个ExcelDocument之前,先保存 GetActiveObject,这样你的脚本就知道在退出时是否需要关闭Excel程序。

简单来说:

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()

撰写回答