iT邦幫忙

1

python 偵測excel關閉後跳出訊息

  • 分享至 

  • xImage

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")

你先把 xi 那時候的值,列印出來看看.
froce iT邦大師 1 級 ‧ 2020-11-11 09:59:51 檢舉
這需求幹麻一定要用xlsx硬幹?
直接用tk跳一個視窗就好。
print("close ok")改成用tk顯示,結案。
ccutmis iT邦高手 2 級 ‧ 2020-11-11 10:21:53 檢舉
@froce
硬幹才是真男人... ^^"

Q: 真男人在哪可以找得到? A: 監獄。
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
0
ccutmis
iT邦高手 2 級 ‧ 2020-11-10 21:14:30
最佳解答

這邊提供一個土法鍊鋼的方法給您參考,
假設你的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了,希望對新手有幫助!

看更多先前的回應...收起先前的回應...
ckp6250 iT邦好手 1 級 ‧ 2020-11-10 21:26:45 檢舉

我猜這招可能有後遺症,

excel.exe 有可能是 python 開的,也有可能是使用者自己事先開了excel 而暫時縮小放在工作列上。

用這招的話,會不會濫殺無辜啊?

ccutmis iT邦高手 2 級 ‧ 2020-11-10 21:30:53 檢舉

搞不好喔 哈哈
先看看樓主反應怎麼樣 如果不行再想PLAN B...

ccutmis iT邦高手 2 級 ‧ 2020-11-11 09:10:56 檢舉

已更新 PLAN B 的作法,用視窗標題是否符合來判斷。

ckp6250 iT邦好手 1 級 ‧ 2020-11-11 11:21:00 檢舉

ccutmis 大大,效率真高。

ccutmis iT邦高手 2 級 ‧ 2020-11-11 12:14:24 檢舉

邦友的好建議 當然要用高規則對應
/images/emoticon/emoticon82.gif

wd_811 iT邦新手 5 級 ‧ 2020-11-12 15:53:26 檢舉

真是太感謝ccutmis 大大了!
PLAN A 確實可以沒錯,但與ccutmis大大說的一樣,會有使用者開啟的EXCEL會被誤殺
PLAN B則可使用。真的非常謝謝您!! /images/emoticon/emoticon41.gif

ccutmis iT邦高手 2 級 ‧ 2020-11-13 08:27:53 檢舉

不客氣,很高興能幫上忙~ :)

0
海綿寶寶
iT邦大神 1 級 ‧ 2020-11-11 09:04:22

你要 Excel;參考這篇用 Notepad.exe 的範例

如果你沒有要「用程式操作 Excel」
只是要「開啟 Excel 給使用者自己使用」的話
其實不用什麼 COM 的寫法
只要用上面那個範例的寫法就夠了

真厲害,三週就在寫 COM...
一般三週不是還在寫爬蟲嗎?dataFrame?
/images/emoticon/emoticon19.gif

我要發表回答

立即登入回答