如何让Excel VBA等待IE中打开的文档打印完成再执行?
问题描述
我需要打印从网页下载后在IE浏览器中打开的文档(该文档页面没有检查元素选项),目前使用SendKeys可以实现打印操作,但当文件较大时,会弹出“打印进行中”的进度窗口。Application.Wait无法确定合适的等待时长,请教如何让宏暂停执行直至打印进度完成?
当前使用的打印函数
Function Sample(tet As Variant) Dim IE_Tab As SHDocVw.InternetExplorer, ie As InternetExplorer Dim HTML_Doc As MSHTML.HTMLDocument Dim SH_Win As SHDocVw.ShellWindows, sh As Object Dim T_Str As String Set SH_Win = New SHDocVw.ShellWindows For Each IE_Tab In SH_Win T_Str = IE_Tab.LocationURL If T_Str = tet Then Application.Wait (Now + TimeValue("00:00:05")) Set sh = CreateObject("WScript.Shell") 'this command just populates the print dialog box, it worked fine only if i print an web page here iam trying to print a document opened as IE IE_Tab.ExecWB OLECMDID_PRINT, OLECMDEXECOPT_DODEFAULT, 2, 0 sh.AppActivate "Print" Application.Wait (Now + TimeValue("00:00:02")) sh.SendKeys "c", 1 Application.Wait (Now + TimeValue("00:00:02")) sh.SendKeys ("{ENTER}") IE_Tab.Quit Exit For End If Next End Function
相关窗口截图
- 打印窗口:

- 打印进度窗口:

解决方案
固定时长的Application.Wait确实不靠谱,尤其是处理大文件时,我们可以通过Windows API函数来检测“打印进行中”窗口的存在,循环等待直到该窗口消失,再继续执行后续代码。
步骤1:添加API声明
在VBA模块的最顶部添加以下API函数声明,用来查找系统窗口:
Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" _ (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr Private Declare PtrSafe Function FindWindowEx Lib "user32" Alias "FindWindowExA" _ (ByVal hWnd1 As LongPtr, ByVal hWnd2 As LongPtr, ByVal lpsz1 As String, _ ByVal lpsz2 As String) As LongPtr
注:如果使用32位Office,去掉
PtrSafe并将LongPtr替换为Long即可。
步骤2:修改打印函数,添加智能等待逻辑
我们在发送打印确认的Enter键后,加入循环检测逻辑,直到“打印进行中”窗口消失再关闭IE标签。修改后的函数如下:
Function Sample(tet As Variant) Dim IE_Tab As SHDocVw.InternetExplorer, ie As InternetExplorer Dim HTML_Doc As MSHTML.HTMLDocument Dim SH_Win As SHDocVw.ShellWindows, sh As Object Dim T_Str As String Dim progressWnd As LongPtr Set SH_Win = New SHDocVw.ShellWindows For Each IE_Tab In SH_Win T_Str = IE_Tab.LocationURL If T_Str = tet Then Application.Wait (Now + TimeValue("00:00:05")) Set sh = CreateObject("WScript.Shell") ' 触发打印对话框 IE_Tab.ExecWB OLECMDID_PRINT, OLECMDEXECOPT_DODEFAULT, 2, 0 sh.AppActivate "Print" Application.Wait (Now + TimeValue("00:00:02")) sh.SendKeys "c", 1 Application.Wait (Now + TimeValue("00:00:02")) sh.SendKeys "{ENTER}" ' 循环等待打印进度窗口消失 Do ' 根据你的进度窗口标题查找窗口,标题不对请自行修改 progressWnd = FindWindow(vbNullString, "打印进行中") ' 释放CPU资源,避免程序假死 DoEvents ' 每500毫秒检测一次 Application.Wait (Now + TimeValue("00:00:00.5")) Loop While progressWnd <> 0 ' 打印完成后关闭IE标签 IE_Tab.Quit Exit For End If Next End Function
关键说明
- 如果你的打印进度窗口标题不是“打印进行中”,请替换
FindWindow函数的第二个参数为实际窗口标题。 DoEvents能让Excel在等待期间响应其他操作,避免出现程序无响应的情况。- 500毫秒的检测间隔可以根据需要调整,既保证响应速度,又不会过度占用系统资源。
内容的提问来源于stack exchange,提问作者arun v




