python三週新手,想請前輩們指導....
用python寫了以下程式,開啟了名為"test.xlsx"的excel檔案
然後想偵測使用者用完、關閉了"test.xlsx"後,跳出 "close ok"的訊息
但不曉得該如何寫?
如果寫
if xl.Workbooks.Count==0:
print("close ok")
好像無法再使用者關閉後,顯示訊息。
原程式碼如下:
import win32com.client as win32
xl = win32.gencache.EnsureDispatch('Excel.Application')
my_workbook = "test.xlsx"
xlPath="D:\1python\1Training\" + my_workbook
xl.Workbooks.Open(Filename=xlPath)
xl.Visible = True
if xl.Workbooks.Count==0:
print("close ok")
這邊提供一個土法鍊鋼的方法給您參考,
假設你的EXCEL執行的時候,在tasklist裡的名字叫作'EXCEL.EXE'
(你可以在cmd底下打 tasklist [Enter],看看實際名字為何並作修改)
函式的思路很簡單,就是呼叫函式的時候就進入一個無窮廻圈,然後利用subprocess.check_output()取得tasklist的執行結果給變數task_str,
再用字串尋找函式看'EXCEL.EXE'是否有在task_str裡,
有的話就表示程式還未結束,
那就暫停1秒(這裡的時間可以自行決定加長或縮短,但一定要有個暫停,避免程式卡系統資源),
然後再重覆前面的動作,直到tasklist裡找不到'EXCEL.EXE'就跳出函式~
以下是範例程式:
import subprocess,time,pyautogui
def alert_msg(tmp_msg,tmp_title='MESSAGE'):
pyautogui.alert(text=tmp_msg, title=tmp_title, button='OK')
def wait_until_task_close(task_name):
while True:
task_str = str(subprocess.check_output(['tasklist']))
if task_str.find(task_name)!=-1:
#task仍在執行中
print(task_name,'is still running.')
time.sleep(1)
else:
#task已close
print(task_name,' closed!')
alert_msg(task_name+'已關閉!')
return True
wait_until_task_close('EXCEL.EXE')
要作到類似網頁的Alert彈出訊息的效果,可以用 pyautogui 的 alert()函式。
(記得先在cmd底下打 pip install pyautogui [Enter] 安裝模組)
====================
PLAN B 來了,邦友提到這招可能有後遺症,沒錯,畢竟函式思路在上面寫的很清楚,有些程式是允許可以同時有多個執行實例(process)的,比如說你同時開了"人事.xls"跟"薪資.xls",在tasklist裡面可能會有兩個"EXCEL.EXE",這樣的話上面的範例就會有問題,例如你希望"人事.xls"關閉時會跳出Alert,結果你確實有關閉"人事.xls"了,但因為"薪資.xls"還在執行,所以用tasklist這個思路去判斷的方式就會出包(它沒辦法判斷那個task裡到底開的是人事.xls還是薪資.xls)。
以下用的是另一個方法,改用視窗標題來判斷,視窗標題可以從工作管理員裡面找到,也可以按ALT+TAB在切換視窗圖示時觀察一下視窗標題內容。這裡的思路同樣很簡單,利用pywin32模組,列舉出當前所有工作中視窗的標題,用規則運算式判斷我們要監控的標題是否在內,若是表示還沒關閉,若不在內表示已關閉,彈出訊息的方式跟PLAN A的方式一樣,以下是範例:
import re,win32gui,win32com.client,time,pyautogui
""" 要安裝win32gui相關模組 請在cmd輸入 pip install pypiwin32 """
def window_enum_callback(hwnd, wildcard):
if re.match(".*?"+wildcard+"*", str(win32gui.GetWindowText(hwnd))) is not None:
global handler,win_exist
handler = hwnd
win_exist = True
def find_window_wildcard(wildcard):
global handler,win_exist
handler = None
win_exist = False
win32gui.EnumWindows(window_enum_callback, wildcard)
def alert_msg(tmp_msg,tmp_title='MESSAGE'):
shell = win32com.client.Dispatch("WScript.Shell")
shell.SendKeys('%')
pyautogui.alert(text=tmp_msg, title=tmp_title, button='OK')
def wait_until_task_close(task_name):
global win_exist
while True:
find_window_wildcard(task_name)
if win_exist:
#task仍在執行中
print(task_name,'is still running.')
time.sleep(1)
else:
#task已close
print(task_name,' closed!')
alert_msg(task_name+'已關閉!')
return True
handler=None
win_exist=False
xls_win_title="Microsoft Excel - 人事.xls"
wait_until_task_close(xls_win_title)
print(win_exist)
註: 為了排版好看我把四個空格轉成TAB,樓主如果是習慣用空格縮排記得測試時把所有TAB置換成四個空格。
這兩種判斷方式都有它的用處,我就不刪PLAN A了,希望對新手有幫助!
你要 Excel;參考這篇用 Notepad.exe 的範例
如果你沒有要「用程式操作 Excel」
只是要「開啟 Excel 給使用者自己使用」的話
其實不用什麼 COM 的寫法
只要用上面那個範例的寫法就夠了
真厲害,三週就在寫 COM...
一般三週不是還在寫爬蟲嗎?dataFrame?