最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

如何用 Python 子進程關(guān)閉 Excel 自動化中的彈窗

 更新時間:2021年05月07日 15:01:45   作者:crazyhat  
這篇文章主要介紹了如何用 Python 子進程關(guān)閉 Excel 自動化中的彈窗,幫助大家更好的理解和學習使用python,感興趣的朋友可以了解下

利用Python進行Excel自動化操作的過程中,尤其是涉及VBA時,可能遇到消息框/彈窗(MsgBox)。此時需要人為響應(yīng),否則代碼卡死直至超時 [^1] [^2]。根本的解決方法是VBA代碼中不要出現(xiàn)類似彈窗,但有時我們無權(quán)修改被操作的Excel文件,例如這是我們進行自動化測試的對象。所以本文記錄從代碼角度解決此類問題的方法。

假想場景

使用xlwings(或者其他自動化庫)打開Excel文件test.xlsm,讀取Sheet1!A1單元格內(nèi)容。很簡單的一個操作:

import xlwings as xw

wb = xw.Book('test.xlsm')
msg = wb.sheets('Sheet1').range('A1').value
print(msg)
wb.close()

然而不幸的是,打開工作簿時進行了熱情的歡迎儀式:

Private Sub Workbook_Open()
    MsgBox "Welcome"
    MsgBox "to open"
    MsgBox "this file."
End Sub

第一個彈窗Welcome就卡住了Excel,Python代碼相應(yīng)卡死在第一行。

基本思路

主程序中不可能直接處理或者繞過此類問題,也不能奢望有人隨時蹲守點擊下一步——那就開啟一個子線程來護航吧。因此,解決方案是利用子線程監(jiān)聽并隨時關(guān)閉彈窗,直到主程序圓滿結(jié)束。
解決這個問題,需要以下兩個知識點(基礎(chǔ)知識請課外學習):

  • Python多線程(本文采用threading.Thread)
  • Python界面自動化庫(本文涉及pywinauto和pywin32)

pywinauto方案

pywinauto顧名思義是Windows界面自動化庫,模擬鼠標和鍵盤操作窗體和控件 [^3]。不同于先獲取句柄再獲取屬性的傳統(tǒng)方式,pywinauto的API更加友好和pythonic。例如,兩行代碼搞定窗口捕捉和點擊:

from pywinauto.application import Application

win = Application(backend="win32").connect(title='Microsoft Excel')
win.Dialog.Button.click()

本文采用自定義線程類的方式,啟動線程后自動執(zhí)行run()函數(shù)來完成上述操作。具體代碼如下,注意構(gòu)造函數(shù)中的兩個參數(shù):

  • title 需要捕捉的彈窗的標題,例如Excel默認彈窗的標題為Microsoft Excel
  • interval 監(jiān)聽的頻率,即每隔多少秒檢查一次
# listener.py

import time
from threading import Thread, Event
from pywinauto.application import Application


class MsgBoxListener(Thread):

    def __init__(self, title:str, interval:int):
        Thread.__init__(self)
        self._title = title 
        self._interval = interval 
        self._stop_event = Event()   

    def stop(self): self._stop_event.set()

    @property
    def is_running(self): return not self._stop_event.is_set()

    def run(self):
        while self.is_running:
            try:
                time.sleep(self._interval)
                self._close_msgbox()
            except Exception as e:
                print(e, flush=True)


    def _close_msgbox(self):
        '''Close the default Excel MsgBox with title "Microsoft Excel".'''        
        win = Application(backend="win32").connect(title=self._title)
        win.Dialog.Button.click()


if __name__=='__main__':
    t = MsgBoxListener('Microsoft Excel', 3)
    t.start()
    time.sleep(10)
    t.stop()

于是,整個過程分為三步:

  • 啟動子線程監(jiān)聽彈窗
  • 主線程中打開Excel開始自動化操作
  • 關(guān)閉子線程
import xlwings as xw
from listener import MsgBoxListener

# start listen thread
listener = MsgBoxListener('Microsoft Excel', 3)
listener.start()

# main process as before
wb = xw.Book('test.xlsm')
msg = wb.sheets('Sheet1').range('A1').value
print(msg)
wb.close()

# stop listener thread
listener.stop()

到此問題基本解決,本地運行效果完全達到預(yù)期。但我的真實需求是以系統(tǒng)服務(wù)方式在服務(wù)器上進行Excel文件自動化測試,后續(xù)發(fā)現(xiàn),當以系統(tǒng)服務(wù)方式運行時,pywinauto竟然捕捉不到彈窗!這或許是pywinauto一個潛在的問題 [^4]。

win32gui方案

那就只好轉(zhuǎn)向相對底層的win32gui,所幸完美解決了上述問題。
win32gui是pywin32庫的一部分,所以實際安裝命令是:

pip install pywin32

整個方案和前文描述完全一致,只是替換MsgBoxListener類中關(guān)閉彈窗的方法:

import win32gui, win32con

def _close_msgbox(self):
    # find the top window by title
    hwnd = win32gui.FindWindow(None, self._title)
    if not hwnd: return

    # find child button
    h_btn = win32gui.FindWindowEx(hwnd, None,'Button', None)
    if not h_btn: return

    # show text
    text = win32gui.GetWindowText(h_btn)
    print(text)

    # click button        
    win32gui.PostMessage(h_btn, win32con.WM_LBUTTONDOWN, None, None)
    time.sleep(0.2)
    win32gui.PostMessage(h_btn, win32con.WM_LBUTTONUP, None, None)
    time.sleep(0.2)

更一般的方案

更一般地,當同時存在默認標題和自定義標題的彈窗時,就不便于采用標題方式進行捕捉了。例如

MsgBox "Message with default title.", vbInformation, 
MsgBox "Message with title My App 1", vbInformation, "My App 1"
MsgBox "Message with title My App 2", vbInformation, "My App 2"

那就擴大搜索范圍,依次點擊所有包含確定性描述的按鈕(例如OK,Yes,Confirm)來關(guān)閉彈窗。同理替換MsgBoxListener類的_close_msgbox()方法(同時構(gòu)造函數(shù)中不再需要title參數(shù)):

def _close_msgbox(self):
    '''Click any button ("OK", "Yes" or "Confirm") to close message box.'''
    # get handles of all top windows
    h_windows = []
    win32gui.EnumWindows(lambda hWnd, param: param.append(hWnd), h_windows) 

    # check each window    
    for h_window in h_windows:            
        # get child button with text OK, Yes or Confirm of given window
        h_btn = win32gui.FindWindowEx(h_window, None,'Button', None)
        if not h_btn: continue

        # check button text
        text = win32gui.GetWindowText(h_btn)
        if not text.lower() in ('ok', 'yes', 'confirm'): continue

        # click button
        win32gui.PostMessage(h_btn, win32con.WM_LBUTTONDOWN, None, None)
        time.sleep(0.2)
        win32gui.PostMessage(h_btn, win32con.WM_LBUTTONUP, None, None)
        time.sleep(0.2)

最后,實例演示結(jié)束全文,以后再也不用擔心意外彈窗了。

以上就是如何用 Python 子進程關(guān)閉 Excel 自動化中的彈窗的詳細內(nèi)容,更多關(guān)于Python 子進程關(guān)閉 Excel 彈窗的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • k-means 聚類算法與Python實現(xiàn)代碼

    k-means 聚類算法與Python實現(xiàn)代碼

    這篇文章主要介紹了k-means 聚類算法與Python實現(xiàn)代碼,本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-06-06
  • 夯實基礎(chǔ)python集合的應(yīng)用場景及字符串定義和表示

    夯實基礎(chǔ)python集合的應(yīng)用場景及字符串定義和表示

    這篇文章主要為大家介紹了python集合的應(yīng)用場景及字符串定義和表示,來幫大家夯實基礎(chǔ),有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2023-10-10
  • Python使用matplotlib的pie函數(shù)繪制餅狀圖功能示例

    Python使用matplotlib的pie函數(shù)繪制餅狀圖功能示例

    這篇文章主要介紹了Python使用matplotlib的pie函數(shù)繪制餅狀圖功能,結(jié)合實例形式分析了Python使用matplotlib的pie函數(shù)進行餅狀圖繪制的具體操作技巧,注釋中對pie函數(shù)的用法進行了詳細的說明,便于理解,需要的朋友可以參考下
    2018-01-01
  • 詳解Django緩存處理中Vary頭部的使用

    詳解Django緩存處理中Vary頭部的使用

    這篇文章主要介紹了詳解Django緩存處理中Vary頭部的使用,Django是最具人氣的Python web開發(fā)框架,需要的朋友可以參考下
    2015-07-07
  • Python三十行代碼實現(xiàn)簡單人臉識別的示例代碼

    Python三十行代碼實現(xiàn)簡單人臉識別的示例代碼

    這篇文章主要介紹了Python三十行代碼實現(xiàn)簡單人臉識別的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-03-03
  • Django models文件模型變更錯誤解決

    Django models文件模型變更錯誤解決

    這篇文章主要介紹了Django models文件模型變更錯誤解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-05-05
  • Python實現(xiàn)刪除文件中含“指定內(nèi)容”的行示例

    Python實現(xiàn)刪除文件中含“指定內(nèi)容”的行示例

    這篇文章主要介紹了Python實現(xiàn)刪除文件中含“指定內(nèi)容”的行功能,涉及Python針對文件讀取及字符串遍歷、判斷等相關(guān)操作技巧,需要的朋友可以參考下
    2017-06-06
  • Python簡單實現(xiàn)socket信息發(fā)送與監(jiān)聽功能示例

    Python簡單實現(xiàn)socket信息發(fā)送與監(jiān)聽功能示例

    這篇文章主要介紹了Python簡單實現(xiàn)socket信息發(fā)送與監(jiān)聽功能,結(jié)合實例形式分析了Python基于socket構(gòu)建客戶端與服務(wù)器端通信相關(guān)操作技巧,需要的朋友可以參考下
    2018-01-01
  • Python使用OpenCV庫實現(xiàn)圖像幾何變化

    Python使用OpenCV庫實現(xiàn)圖像幾何變化

    幾何變換是通過數(shù)學變換將圖像的像素從一個位置映射到另一個位置的過程,在圖像處理領(lǐng)域,幾何變換是一個非常重要的操作,它可以改變圖像的位置、大小、方向或形狀,本文將介紹如何利用 Python 的 OpenCV 庫實現(xiàn)圖像的幾何變換,需要的朋友可以參考下
    2024-12-12
  • Python中使用filter過濾列表的一個小技巧分享

    Python中使用filter過濾列表的一個小技巧分享

    這篇文章主要介紹了Python中使用filter過濾列表的一個小技巧分享,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-05-05

最新評論

哈密市| 什邡市| 普安县| 巴彦淖尔市| 麻城市| 恩施市| 普安县| 库车县| 桦甸市| 策勒县| 台北市| 古田县| 汪清县| 工布江达县| 克拉玛依市| 大余县| 阜南县| 新竹市| 招远市| 滦南县| 繁峙县| 宝山区| 石嘴山市| 长宁县| 栾城县| 红安县| 苗栗市| 平昌县| 浪卡子县| 兴山县| 调兵山市| 昌乐县| 荣成市| 兴和县| 祁门县| 黄骅市| 凤阳县| 永和县| 明星| 安图县| 明水县|