There are a lot of examples of VBA and C# code that checks if a workbook is open using the Win API for COM objects, but there is none for python using the pywin32. I tried to use functions like GetObject
and GetItem
but they are not without their challenges. Please see code snippet below with my method for trying to check if the user has closed the workbook. It opens up a workbook and then keeps it open for ten seconds. If the user closes, insanity ensues. Does anyone know the proper way to write this code? Thanks!
# Open an excel, check if its open, wait until user closes or close it after ten seconds
def wait_until_time_or_user_close(excel, gencache=False):
excel = win32.gencache.EnsureDispatch('Excel.Application')
excel.Visible = True
excel.DisplayAlerts = False
wb_open = True
try:
wb = excel.Workbooks.Add() # create new workbook
name = ''.join(wb.Name) # create a new string copy
# - needed because if user closes
# wb, then wb doesn't exist and
# wb.Name throws an error.
seconds = 0
xl = None
while(wb_open and seconds < 10):
xl = win32.GetObject(name)
# excel.Workbooks.getItem(name); # produces AttributeError:
# '<win32com.gen_py.Microsoft Excel 16.0 Object Library.Workbooks instance at 0x1548081920544>'
# object has no attribute 'getItem' (or GetItem)
# Source: https://stackoverflow.com/questions/3156676/checking-if-an-excel-workbook-is-open
wb_open = xl is not None
# give user some time to interact
import time
time.sleep(1)
seconds += 1
finally:
if wb_open:
print("wb closed")
wb.Close(False) # True=save the workbook, False=don't save workbook
excel.Application.Quit()
excel = None
wait_until_time_or_user_close(excel)
Also, does anyone have any recommendations on how to find out different functions and attributes available to a COM object? The pywin32 documentation says the following:
How do I know which methods and properties are available?
Good question. This is hard! You need to use the documentation with the products, or possibly a COM browser. Note however that COM browsers typically rely on these objects registering themselves in certain ways, and many objects to not do this. You are just expected to know.
It says you are just expected to know... well if that is the case where do I go to know this stuff????
One can see the documentation here: http://timgolden.me.uk/pywin32-docs/html/com/win32com/HTML/QuickStartClientCom.html
Here is one way to solve the problem. Add a second try/catch statement. If there are better ways to do this - please recommend them. Also, the second question still stands on the best methods to find out about the Win32 API.
# Open an excel, check if its open, wait until user closes or close it after ten seconds
def wait_until_time_or_user_close(excel, gencache=False):
excel = win32.gencache.EnsureDispatch('Excel.Application')
excel.Visible = True
excel.DisplayAlerts = False
wb_open = True
try:
wb = excel.Workbooks.Add() # create new workbook
seconds = 0
xl = None
while(wb_open and seconds < 10):
try:
xl = win32.GetObject(wb.Name)
except:
wb_open = xl is not None
# give user some time to interact
import time
time.sleep(1)
seconds += 1
finally:
if wb_open:
print("wb closed")
wb.Close(False) # True=save the workbook, False=don't save workbook
excel.Application.Quit()
excel = None
wait_until_time_or_user_close(excel)