所以我有一些使用xlwings在Excel文件xlsm中写入数据的代码。
写完之后,我按下某个按钮进行计算。
有时,Excel中会弹出错误/消息,这很好,但是我想将此消息捕获到python,然后将其写入日志/打印。
另外,我需要与此消息进行交互,在这种情况下,请在消息框中按“确定”
答案 0 :(得分:2)
伙计们,我已经能够使用外部python库解决此问题。
代码如下:
from pywinauto import application as autoWin
app = autoWin.Application()
con = app.connect(title = 'Configuration Error')
msgText = con.Dialog.Static2.texts()[0]
con.Dialog.Button.click()
con.Dialog.Button.click()
print(msgText)
基本上,它的作用是连接到应用程序,然后搜索标题。
在这种情况下为“配置错误”
需要双击才能按“确定”以关闭消息。
第二,它从消息中获取文本,并可以将其转发到我想要的任何地方。
要记住的重要部分,因为这应该是自动化任务,所以应该同时运行,这意味着线程化。
因此,下面是一个简单的Thread类:
class ButtonClicker(Thread):
def __init__(self):
Thread.__init__(self)
self._stop_event = Event()
def stop(self):
self._stop_event.set()
def stopped(self):
return self._stop_event.is_set()
def run(self) -> None:
while True:
time.sleep(3)
try:
app = autoWin.Application()
con = app.connect(title='Configuration Error')
msg_data = con.Dialog.Static2.texts()[0]
while True:
con.Dialog.Button.click()
# con.Dialog.Button.click()
# print(msg_data)
return msg_data
except Exception as e:
print('Excel didnt stuck')
break
当然要实际使用它:
event_handle = ButtonClicker()
event_handle.start()
需要一些操纵才能在不同的代码/场景中工作,但至少我希望以后我会帮助其他人,因为这似乎是一个非常普遍的问题。
答案 1 :(得分:0)
@Danny 的解决方案,即 pywinauto
和 Thread
,在我的本地机器上运行良好,但是当 Excel 在服务器模式下运行时,它似乎无法捕获消息框,例如就我而言,自动化是在本地触发的,并由安装在服务器中的系统服务启动。
pywinauto.findwindows.ElementNotFoundError:
{'title': '<my-wanted-title>', 'backend': 'win32', 'visible_only': False}
终于用另一个python第三方库pywin32
解决了,所以这里提供一个备份方案。
'''
Keep finding message box with specified title and clicking button to close it,
until stopped by the main thread.
'''
import time
from threading import Thread, Event
import win32gui
import win32con
class ButtonClicker(Thread):
def __init__(self, title:str, interval:int):
Thread.__init__(self)
self._title = title
self._interval = interval
self._stop_event = Event()
def stop(self):
'''Stop thread.'''
self._stop_event.set()
@property
def stopped(self):
return self._stop_event.is_set()
def run(self):
while not self.stopped:
try:
time.sleep(self._interval)
self._close_msgbox()
except Exception as e:
print(e, flush=True)
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)
if __name__=='__main__':
t = ButtonClicker('Configuration Error', 3)
t.start()
time.sleep(10)
t.stop()