As per What defines which Excel instance an Excel.Application COM object connects to? :
- You connect to an existing Excel instance with
win32com.client.GetActiveObject(<ProgID>)
- You can only connect to one specific running Excel instance. If there are multiple running, the COM class always selects one of them according to certain logic (I call it "the "priority" one" further below).
- You cannot connect to Excel instances running as different users (this includes with vs without elevation)
So if your files are open in multiple Excel instances, or in an instance that is not the "priority" one, the only way to iterate over them is to repeatedly connect to an existing instance then terminate it so that another instance comes "on top" (until there are none left in the 1st case, or until you get to the right one in the 2nd case). If there are instances running as different users, you'll need to run your code multiple times as all the corresponding users.
- Fortunately, there can normally only be one "foreground" (i.e. visible and manually started) Excel instance per user which all the workbooks you open go to -- even though they show as separate windows (normally = unless you manually fiddled with the
Application.Visible
property), and any "background" ones (launched via COM programmatically) take priority.
- So it should probably be safe to terminate any invisible instances and stop once you get to a visible one.
If however all your files are open in a single Excel instance that is the "priority" one, then you connect to it, iterate over the open workbooks and close the appropriate ones:
import os.path
import win32com.client
x = win32com.client.GetActiveObject("Excel.Application")
for wb in x.Workbooks:
if os.path.dirname(wb.FullName) == your_dir:
wb.Close(True) # do specify the SaveChanges arg (as shown) --
# otherwise, Excel will ask you interactively if there are changes,
# hanging the program until you make a choice
# (unless that's what you want, of course)
del wb
del x