VBA IE自动化-等待下载完成
我正在尝试通过Internet explorer自动完成一些任务,包括下载文件,然后将其复制到其他目录并重命名。 我或多或少成功地找到了有关如何执行此操作的信息,代码正在运行,但有例外,因此如果有人能帮助我改进此代码,我将不胜感激 我想做两件事:VBA IE自动化-等待下载完成,vba,internet-explorer,download,browser-automation,ie-automation,Vba,Internet Explorer,Download,Browser Automation,Ie Automation,我正在尝试通过Internet explorer自动完成一些任务,包括下载文件,然后将其复制到其他目录并重命名。 我或多或少成功地找到了有关如何执行此操作的信息,代码正在运行,但有例外,因此如果有人能帮助我改进此代码,我将不胜感激 我想做两件事: 插入一个循环,这样脚本将等待某些元素出现,然后才能继续执行。我已经在页面上找到了一些东西,但是,我也希望像这里建议的那样,构建一个最长的等待时间 当代码正在下载文件时,它还应该等待下载完成,然后再继续。目前我正在使用“wait”命令,但下载时间可能会有
Option Explicit
#If VBA7 Then
Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds 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
#Else
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" _
(ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, _
ByVal lpsz2 As String) As Long
#End If
Sub MyIEauto()
Dim ieApp As InternetExplorer
Dim ieDoc As Object
Set ieApp = New InternetExplorer
ieApp.Visible = True
ieApp.navigate "https://docs.microsoft.com/en-us/power-bi/sample-financial-download"
Do While ieApp.Busy: DoEvents: Loop
Do Until ieApp.readyState = READYSTATE_COMPLETE: DoEvents: Loop
ieApp.navigate "http://go.microsoft.com/fwlink/?LinkID=521962"
Do While ieApp.Busy: DoEvents: Loop
Do Until ieApp.readyState = READYSTATE_COMPLETE: DoEvents: Loop
Dim AutomationObj As IUIAutomation
Dim WindowElement As IUIAutomationElement
Dim Button As IUIAutomationElement
Dim hWnd As LongPtr
Set AutomationObj = New CUIAutomation
Do While ieApp.Busy Or ieApp.readyState <> 4: DoEvents: Loop
Application.Wait (Now + TimeValue("0:00:05"))
hWnd = ieApp.hWnd
hWnd = FindWindowEx(hWnd, 0, "Frame Notification Bar", vbNullString)
If hWnd = 0 Then Exit Sub
Set WindowElement = AutomationObj.ElementFromHandle(ByVal hWnd)
Dim iCnd As IUIAutomationCondition
Set iCnd = AutomationObj.CreatePropertyCondition(UIA_NamePropertyId, "Save")
Set Button = WindowElement.FindFirst(TreeScope_Subtree, iCnd)
Dim InvokePattern As IUIAutomationInvokePattern
Set InvokePattern = Button.GetCurrentPattern(UIA_InvokePatternId)
InvokePattern.Invoke
Application.Wait (Now + TimeValue("0:00:05"))
FileCopy "C:\Users\Name\Downloads\Financial Sample.xlsx", "C:\Users\Name\Desktop\Financial Sample.xlsx"
Name "C:\Users\Name\Desktop\Financial Sample.xlsx" As "C:\Users\Name\Desktop\Hello.xlsx"
Application.Wait (Now + TimeValue("0:00:01"))
Dim KillFile As String
KillFile = "C:\Users\Name\Downloads\Financial Sample.xlsx"
If Len(Dir$(KillFile)) > 0 Then
SetAttr KillFile, vbNormal
Kill KillFile
End If
End Sub
选项显式
#如果是VBA7,则
声明PtrSafe子睡眠库“kernel32”(ByVal dwr作为LongPtr)
私有声明PtrSafe函数FindWindowEx Lib“user32”别名“FindWindowExA”_
(ByVal hWnd1作为LongPtr,ByVal hWnd2作为LongPtr,ByVal lpsz1作为字符串_
ByVal lpsz2作为字符串)作为LongPtr
#否则
公共声明子睡眠库“kernel32”(ByVal的长度为毫秒)
私有声明函数FindWindowEx Lib“user32”别名“FindWindowExA”_
(ByVal hWnd1为长,ByVal hWnd2为长,ByVal lpsz1为字符串_
ByVal lpsz2(作为字符串)一样长
#如果结束
次MyIEauto()
Dim ieApp作为InternetExplorer
Dim ieDoc作为对象
设置ieApp=新的InternetExplorer
ieApp.Visible=True
ieApp.navigate“https://docs.microsoft.com/en-us/power-bi/sample-financial-download"
在ieApp.Busy:DoEvents:Loop时执行
直到ieApp.readyState=readyState\u完成:DoEvents:Loop
ieApp.navigate“http://go.microsoft.com/fwlink/?LinkID=521962"
在ieApp.Busy:DoEvents:Loop时执行
直到ieApp.readyState=readyState\u完成:DoEvents:Loop
Dim Automation作为iUI自动化
将WindowElement调暗为IUIAutomationeElement
调暗按钮作为IUIAutomationeElement
变暗hWnd为长PTR
Set AutomationObj=新CUI自动化
当ieApp.Busy或ieApp.readyState 4:DoEvents:Loop时执行
Application.Wait(现在+时间值(“0:00:05”))
hWnd=ieApp.hWnd
hWnd=FindWindowEx(hWnd,0,“帧通知栏”,vbNullString)
如果hWnd=0,则退出Sub
设置WindowElement=AutomationObj.ElementFromHandle(ByVal hWnd)
Dim iCnd作为IUIAutomation条件
设置iCnd=AutomationObj.CreatePropertyCondition(UIA_NamePropertyId,“保存”)
Set Button=WindowElement.FindFirst(TreeScope\u子树,iCnd)
Dim InvokePattern作为IUIAutomationInvokePattern
设置InvokePattern=Button.GetCurrentPattern(UIA_InvokePatternId)
InvokePattern.Invoke
Application.Wait(现在+时间值(“0:00:05”))
文件副本“C:\Users\Name\Downloads\Financial Sample.xlsx”,“C:\Users\Name\Desktop\Financial Sample.xlsx”
将“C:\Users\Name\Desktop\Financial Sample.xlsx”命名为“C:\Users\Name\Desktop\Hello.xlsx”
Application.Wait(现在+时间值(“0:00:01”))
将文件设置为字符串
KillFile=“C:\Users\Name\Downloads\Financial Sample.xlsx”
如果Len(Dir$(KillFile))>0,则
SetAttr KillFile,vbNormal
杀死杀手档案
如果结束
端接头
您可以使用函数或FSOGetFile
和File.Size
,并运行一个循环,等待1或2秒,直到文件大小停止更改?这意味着下载已经完成
{EDIT}下面是一个使用后期绑定的FileSystemObject获取文件大小的函数:
如果目标是从网站下载文件(如Financial Sample.xlsx
fromhttps://docs.microsoft.com/en-us/power-bi/sample-financial-download
-而且页面实际上不需要显示-还有另一种方法,您可能会发现问题较少
正如您可能已经发现的那样,以编程方式等待页面加载、单击按钮等可能会成为一个令人头痛的问题。这会增加不可预见/不可预测的因素,如网络延迟、源更改等
以下方法应适用于任何文件URL(和任何文件类型),即使页面不包含实际链接(如许多视频共享网站)
以您的示例为例,我们可以像这样使用它:
downloadFile "http://go.microsoft.com/fwlink/?LinkID=521962", _
"C:\Users\Name\Desktop\Financial Sample.xlsx"
文件将保存到指定的目标
可能的安全警告(并防止)
使用此方法,您可能会弹出一个安全警告窗口(取决于您的设置和Windows版本)
这可以通过多种方式轻松解决:(#3或#4是我的首选)
手动单击“是”
通过编程方式“查找”类似于代码示例的窗口,单击“是”
在Windows Internet选项中启用选项“跨域访问数据源”
:
- 按Windows键,键入“Internet选项”,然后按Enter键
- 单击
安全性
选项卡
- 在
Internet
下,单击自定义级别…
- 在“杂项”下,选择“跨域访问数据源”
使用文件的直接URL而不是间接链接(如Microsoft)
Sub downloadFile(url As String, filePath As String)
'Download file located at [url]; save to path/filename [filePath]
Dim WinHttpReq As Object, attempts As Integer, oStream
attempts = 3 'in case of error, try up to 3 times
On Error GoTo TryAgain
TryAgain:
attempts = attempts - 1
Err.Clear
If attempts > 0 Then
Set WinHttpReq = CreateObject("Microsoft.XMLHTTP")
WinHttpReq.Open "GET", url, False
WinHttpReq.send
If WinHttpReq.Status = 200 Then
Set oStream = CreateObject("ADODB.Stream")
oStream.Open
oStream.Type = 1
oStream.Write WinHttpReq.responseBody
oStream.SaveToFile filePath, 1 ' 1 = no overwrite, 2 = overwrite
oStream.Close
Debug.Print "Saved [" & url & "] to [" & filePath & "]"
End If
Else
Debug.Print "Error downloading [" & url & "]"
End If
End Sub
downloadFile "http://go.microsoft.com/fwlink/?LinkID=521962", _
"C:\Users\Name\Desktop\Financial Sample.xlsx"
downloadFile "http://download.microsoft.com/download/1/4/E/14EDED28-6C58-4055-A65C-23B4DA81C4DE/Financial%20Sample.xlsx", _
"C:\Users\Name\Desktop\Financial Sample.xlsx"
Option Explicit
#If VBA7 Then
Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds 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
#Else
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" _
(ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, _
ByVal lpsz2 As String) As Long
#End If
Sub MyIEauto()
Dim ieApp As InternetExplorer
Dim ieDoc As Object
Const DebugMode As Boolean = False
Set ieApp = New InternetExplorer
ieApp.Visible = True
ieApp.navigate "https://docs.microsoft.com/en-us/power-bi/sample-financial-download"
Do While ieApp.Busy: DoEvents: Loop
Do Until ieApp.readyState = READYSTATE_COMPLETE: DoEvents: Loop
ieApp.navigate "http://go.microsoft.com/fwlink/?LinkID=521962"
Do While ieApp.Busy: DoEvents: Loop
Do Until ieApp.readyState = READYSTATE_COMPLETE: DoEvents: Loop
Dim AutomationObj As IUIAutomation
Dim WindowElement As IUIAutomationElement
Dim Button As IUIAutomationElement
Dim hWnd As LongPtr
Set AutomationObj = New CUIAutomation
Do While ieApp.Busy Or ieApp.readyState <> 4: DoEvents: Loop
Application.Wait (Now + TimeValue("0:00:05"))
hWnd = ieApp.hWnd
hWnd = FindWindowEx(hWnd, 0, "Frame Notification Bar", vbNullString)
If hWnd = 0 Then Exit Sub
Set WindowElement = AutomationObj.ElementFromHandle(ByVal hWnd)
Dim iCnd As IUIAutomationCondition
Set iCnd = AutomationObj.CreatePropertyCondition(UIA_NamePropertyId, "Save")
Set Button = WindowElement.FindFirst(TreeScope_Subtree, iCnd)
Dim InvokePattern As IUIAutomationInvokePattern
Set InvokePattern = Button.GetCurrentPattern(UIA_InvokePatternId)
InvokePattern.Invoke
Do
Set iCnd = AutomationObj.CreatePropertyCondition(UIA_NamePropertyId, "Open folder")
Set Button = WindowElement.FindFirst(TreeScope_Subtree, iCnd)
Sleep 200
If DebugMode Then Debug.Print Format(Now, "hh:mm:ss"); "Open folder"
DoEvents
Loop While Button Is Nothing
FileCopy "C:\Users\" & Environ("UserName") & "\Downloads\Financial Sample.xlsx", "C:\Users\" & Environ("UserName") & "\Desktop\Financial Sample.xlsx"
Name "C:\Users\" & Environ("UserName") & "\Desktop\Financial Sample.xlsx" As "C:\Users\" & Environ("UserName") & "\Desktop\Hello.xlsx"
Application.Wait (Now + TimeValue("0:00:01"))
Dim KillFile As String
KillFile = "C:\Users\" & Environ("UserName") & "\Downloads\Financial Sample.xlsx"
If Len(Dir$(KillFile)) > 0 Then
SetAttr KillFile, vbNormal
Kill KillFile
End If
End Sub
intCounter = 0
Do Until IsObject(objIE.document.getElementById("btnLogIn")) = True Or intCounter > 3
DoEvents
Application.Wait (Now + TimeValue("0:00:01"))
intCounter = intCounter + 1
If intCounter = 4 Then
MsgBox "Time out."
End If
Loop