views:

865

answers:

3

I've got a legacy application which is implemented in a number of Excel workbooks. It's not something that I have the authority to re-implement, however another application that I do maintain does need to be able to call functions in the Excel workbook.

It's been given a python interface using the Win32Com library. Other processes can call functions in my python package which in turn invokes the functions I need via Win32Com.

Unfortunately COM does not allow me to specify a particular COM process, so at the moment no matter how powerful my server I can only control one instance of Excel at a time on the computer. If I were to try to run more than one instance of excel there would be no way of ensuring that the python layer is bound to a specific Excel instance.

I'd like to be able to run more than 1 of my excel applications on my Windows server concurrently. Is there a way to do this? For example, could I compartmentalize my environment so that I could run as many Excel _ Python combinations as my application will support?

+1  A: 

If you application uses a single excel file which contains macros which you call, I fear the answer is probably no since aside from COM Excel does not allow the same file to be opened with the same name (even if in different directories). You may be able to get around this by dynamically copying the file to another name before opening.

My python knowledge isn't huge, but in most languages there is a way of specifying when you create a COM object whether you wish it to be a new object or connect to a preexisting instance by default. Check the python docs for something along these lines.

Can you list the kind of specific problems you are having and exactly what you are hoping to do?

Toby Allen
+2  A: 

I don't know a thing about Python, unfortunately, but if it works through COM, Excel is not a Single-Instance application, so you should be able to create as many instances of Excel as memory permits.

Using C# you can create multiple Excel Application instances via:

Excel.Application xlApp1 = new Excel.Application();
Excel.Application xlApp2 = new Excel.Application();
Excel.Application xlApp3 = new Excel.Application();

Using late binding in C# you can use:

object objXL1 = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application"));
object objXL2 = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application"));
object objXL3 = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application"));

If using VB.NET, VB6 or VBA you can use CreateObject as follows:

Dim objXL1 As Object = CreateObject("Excel.Application")
Dim objXL2 As Object = CreateObject("Excel.Application")
Dim objXL3 As Object = CreateObject("Excel.Application")

Unfortunately, in Python, I don't have a clue. But unless there is some limitation to Python (which I can't imagine?) then I would think that it's very do-able.

That said, the idea of having multiple instances of Excel acting as some kind of server for other operations sounds pretty dicy... I'd be careful to test what you are doing, especially with respect to how many instances you can have open at once without running out of memory and what happens to the calling program if Excel crashed for some reason.

Mike Rosenblum
Yeah it's no problem starting two different instances of Excel; just that you can't have multiple Excel applications open and grab their COM process using GetObject...
Jon Fournier
Ok, that is true... but anyone using Excel for the back-end of any service should never be hijacking other Excel processes via GetObject(). It should only create and use its own Excel instances. Otherwise, your application could clash with a user or another process using the Excel instance. :-(
Mike Rosenblum
A: 

See "Starting a new instance of a COM application" by Tim Golden, also referenced here, which give the hint to use

xl_app = DispatchEx("Excel.Application")

rather than

xl_app = Dispatch("Excel.Application")

to start a separate process. So you should be able to do:

xl_app_1 = DispatchEx("Excel.Application")
xl_app_2 = DispatchEx("Excel.Application")
xl_app_3 = DispatchEx("Excel.Application")

Note that when you're done, to close the app, I've found it's necessary to do:

xl_app.Quit()
xl_app = None

I found the process won't shut down until xl_app = None, that is, the Python COM object's reference count goes to zero.

Note I'm having one remaining problem: while my Python program is running, if I double-click an Excel file in Explorer (at least, on Win2k), it ends up opening the file in the existing Excel process that Python started (which is running hidden), which disrupts the Python program. I haven't yet found a resolution for this.

Craig McQueen