14

I'm automating some excel related tasks which take a long time.

I'm creating an excel instance using:

excel = win32.gencache.EnsureDispatch('Excel.Application')
wb = excel.Workbooks.Add()

however, after the script starts running, if i select an open excel workbook(not the one python is working on), The python script crashes. However, if I open a new excel workbook and type stuff into it, the python script is unaffected.

Is there a particular way I can call excel to prevent this from happening? Or any other solution?

EDIT: This seems to work.

excel = win32.DispatchEx('Excel.Application')
jck
  • 1,910
  • 4
  • 18
  • 25

2 Answers2

9

Here's a way to create a new instance and use static cache (which is faster and gives an ability to use kwargs):

import sys
import shutil
import pythoncom
from win32com.client import gencache

def EnsureDispatchEx(clsid, new_instance=True):
    """Create a new COM instance and ensure cache is built,
       unset read-only gencache flag"""
    if new_instance:
        clsid = pythoncom.CoCreateInstanceEx(clsid, None, pythoncom.CLSCTX_SERVER,
                                             None, (pythoncom.IID_IDispatch,))[0]
    if gencache.is_readonly:
        #fix for "freezed" app: py2exe.org/index.cgi/UsingEnsureDispatch
        gencache.is_readonly = False
        gencache.Rebuild()
    try:
        return gencache.EnsureDispatch(clsid)
    except (KeyError, AttributeError):  # no attribute 'CLSIDToClassMap'
        # something went wrong, reset cache
        shutil.rmtree(gencache.GetGeneratePath())
        for i in [i for i in sys.modules if i.startswith("win32com.gen_py.")]:
            del sys.modules[i]
        return gencache.EnsureDispatch(clsid)

wdApp = EnsureDispatchEx("Word.Application")

Upd: improved version resets cache on error

Winand
  • 2,093
  • 3
  • 28
  • 48
0

Why don't you do it like this?

from win32com import client
excel=client.Dispatch("Excel.Application")
Arnab Ghosal
  • 483
  • 1
  • 4
  • 11
  • 5
    If you don't run the make.py to generate a "static com proxy" then `EnsureDispatch` is required to access the `win32com.constants`. See this link: http://timgolden.me.uk/python/win32_how_do_i/generate-a-static-com-proxy.html Furthermore, `Dispatch` doesn't solve his problem, the solution is `DispatchEx()` – supermitch Mar 22 '13 at 23:33
  • 1
    This won't start a new Excel process if one is already running as the same user. See https://stackoverflow.com/questions/52571993/why-do-i-get-different-lists-of-open-workbooks-in-excel-com-based-on-which-ide-e/52572968#52572968 – ivan_pozdeev Apr 08 '19 at 20:26