如何让VBA开始下载文件,而不是等到文件完成后再继续下一行代码
我正在尝试优化生成报告的VBA应用程序 此报表要求应用程序下载并嵌入多个图像。 我认为这是应用程序中最大的瓶颈 我的第一次尝试是让VBA执行Powershell命令,该命令将在生成报告的早期下载图像,然后应用程序将在处理完数据后从HD嵌入图像。 我的工作环境阻止VBA执行shell脚本 在几次不重要的失败尝试之后(尝试用一个新的excel应用程序打开另一个/xlsm工作簿,独立于我的vba线程,并使用一个on open执行和它的变体),我来到这里征求建议 如何使用vba开始下载映像(使用任何本机windows 10应用程序/命令/进程/…),而不是等到下载完成后再转到下一行代码 稍后在应用程序中,我将使用代码扫描目标目录,以确定文件是否已下载完毕,否则将休眠并在失败之前重复x次 更新:根据评论,我认为我非常接近解决方案。我已经在这个更新的底部包含了我目前正在使用的代码。现在的问题是,只要我之前至少向同一个url发出过一次请求,它就会快速下载该文件。 在第一个请求中,它挂起“oXMLHTTP.send”的时间比我预期的通过浏览器下载文件所需的时间稍长,然后出于某种原因调整自身大小 有谁能帮我解决这个悬而未决的问题和/或解释一下为什么这段代码调用“Workbook\u WindowResize” 这在我的工作中时有发生。看着Fiddler,我可以看出只有两个请求发出 结果200: 结果200: 结果和代码 在一个全新的工作簿中,我粘贴了更新结束时找到的代码。 这是我在即时窗口中看到的如何让VBA开始下载文件,而不是等到文件完成后再继续下一行代码,vba,download,Vba,Download,我正在尝试优化生成报告的VBA应用程序 此报表要求应用程序下载并嵌入多个图像。 我认为这是应用程序中最大的瓶颈 我的第一次尝试是让VBA执行Powershell命令,该命令将在生成报告的早期下载图像,然后应用程序将在处理完数据后从HD嵌入图像。 我的工作环境阻止VBA执行shell脚本 在几次不重要的失败尝试之后(尝试用一个新的excel应用程序打开另一个/xlsm工作簿,独立于我的vba线程,并使用一个on open执行和它的变体),我来到这里征求建议 如何使用vba开始下载映像(使用任何本机
A took: 33375milliseconds
Pre DoEvents
Workbook_WindowResized
Post DoEvents
B took: 593milliseconds
Pre DoEvents
Post DoEvents
C took: 33797milliseconds
Pre DoEvents
Workbook_WindowResized
Post DoEvents
Do work
Pre DoEvents
Post DoEvents
a done
b done
c done
此工作簿代码
Private mlngStart As Long
Private Declare Function GetTickCount Lib "kernel32" () As Long
Public Sub StartTimer()
mlngStart = GetTickCount
End Sub
Public Function EndTimer() As Long
EndTimer = (GetTickCount - mlngStart)
End Function
Function StartDownload(ByVal vWebFile As String, sPath As String) As Object
Dim oXHTTP As Object
Dim oStream As Object
Set oXHTTP = CreateObject("MSXML2.XMLHTTP.3.0")
Set oStream = CreateObject("ADODB.Stream")
Application.StatusBar = "Fetching " & vWebFile & " as " & sPath
oXHTTP.Open "GET", vWebFile, False
oXHTTP.send
With oStream
.Type = 1 'adTypeBinary
.Open
.Write oXHTTP.responseBody
.SaveToFile sPath, 2 'adSaveCreateOverWrite
.Close
End With
Set StartDownload = oXHTTP
Set oStream = Nothing
Application.StatusBar = False
End Function
Sub FinishDownload(ByRef oXMLHTTP, ByVal vLocalFile As String)
'Wait for request to finish
Do While oXMLHTTP.readyState <> 4
DoEvents
Loop
End Sub
Function foo()
Dim dest As String
dest = "C:\sandbox\"
Dim a, b, c As Object
DoEvents
Url = "http://ipv4.download.thinkbroadband.com/50MB.zip?randomizer=ff" & Str(Math.Round(Math.Rnd(12) * 1000, 0))
Call StartTimer
Set a = StartDownload(Url, dest & "a.zip")
Debug.Print "A took: " & EndTimer & "milliseconds"
Debug.Print "Pre DoEvents"
DoEvents
Debug.Print "Post DoEvents"
Call StartTimer
Set b = StartDownload(Url, dest & "b.zip")
Debug.Print "B took: " & EndTimer & "milliseconds"
Debug.Print "Pre DoEvents"
DoEvents
Debug.Print "Post DoEvents"
Url = "http://ipv4.download.thinkbroadband.com/50MB.zip?randomizer=ee" & Str(Math.Round(Math.Rnd(12) * 1000, 0))
Call StartTimer
Set c = StartDownload(Url, dest & "c.zip")
Debug.Print "C took: " & EndTimer & "milliseconds"
Debug.Print "Pre DoEvents"
DoEvents
Debug.Print "Post DoEvents"
Debug.Print ("Do work")
Call bar
Debug.Print "Pre DoEvents"
DoEvents
Debug.Print "Post DoEvents"
Call FinishDownload(a, dest & "a.zip")
Debug.Print ("a done")
Call FinishDownload(b, dest & "b.zip")
Debug.Print ("b done")
Call FinishDownload(c, dest & "c.zip")
Debug.Print ("c done")
End Function
Function Download_File(ByVal vWebFile As String, ByVal vLocalFile As String) As Boolean
Dim oXMLHTTP As Object, i As Long, vFF As Long, oResp() As Byte
'You can also set a ref. to Microsoft XML, and Dim oXMLHTTP as MSXML2.XMLHTTP
Set oXMLHTTP = CreateObject("MSXML2.XMLHTTP")
oXMLHTTP.Open "GET", vWebFile, False 'Open socket to get the website
oXMLHTTP.send 'send request
'Wait for request to finish
Do While oXMLHTTP.readyState <> 4
DoEvents
Loop
oResp = oXMLHTTP.responseBody 'Returns the results as a byte array
'Create local file and save results to it
vFF = FreeFile
If Dir(vLocalFile) <> "" Then Kill vLocalFile
Open vLocalFile For Binary As #vFF
Put #vFF, , oResp
Close #vFF
'Clear memory
Set oXMLHTTP = Nothing
End Function
Sub bar()
Dim F As Integer
F = FreeFile
Open "C:\sandbox\" & "\example.txt" For Output As F
Close #F
End Sub
Private Sub Workbook_WindowResize(ByVal Wn As Window)
Debug.Print "Workbook_WindowResized"
End Sub
Private mlngStart尽可能长
私有声明函数GetTickCount Lib“kernel32”()的长度为
公共子StartTimer()
mlngStart=GetTickCount
端接头
公共函数EndTimer()的长度为
EndTimer=(GetTickCount-mlngStart)
端函数
函数StartDownload(ByVal vWebFile作为字符串,sPath作为字符串)作为对象
Dim oXHTTP作为对象
作为对象的暗淡光束
设置oXHTTP=CreateObject(“MSXML2.XMLHTTP.3.0”)
设置oStream=CreateObject(“ADODB.Stream”)
Application.StatusBar=“Fetching”&vWebFile&“as”&sPath
oXHTTP.Open“GET”,vWebFile,False
oXHTTP.send
与奥斯特雷姆
.Type=1'adTypeBinary
打开
.Write-oXHTTP.responseBody
.SaveToFile sPath,2'adSaveCreateOverWrite
.结束
以
设置StartDownload=oXHTTP
设置oStream=Nothing
Application.StatusBar=False
端函数
Sub FinishDownload(ByRef-oXMLHTTP,ByVal-vLocalFile作为字符串)
'等待请求完成
执行oXMLHTTP.readyState 4时
多芬特
环
端接头
函数foo()
将dest变暗为字符串
dest=“C:\sandbox\”
作为对象的尺寸a、b、c
多芬特
Url=”http://ipv4.download.thinkbroadband.com/50MB.zip?randomizer=ff&Str(数学圆整(数学圆整(12)*1000,0))
打电话给StartTimer
设置a=StartDownload(Url、dest和“a.zip”)
Debug.Print“A take:&EndTimer&“毫秒”
调试。打印“前置事件”
多芬特
调试。打印“Post DoEvents”
打电话给StartTimer
设置b=StartDownload(Url、dest和“b.zip”)
Debug.Print“B take:”&EndTimer&“毫秒”
调试。打印“前置事件”
多芬特
调试。打印“Post DoEvents”
Url=”http://ipv4.download.thinkbroadband.com/50MB.zip?randomizer=ee&Str(数学圆整(数学圆整(12)*1000,0))
打电话给StartTimer
设置c=StartDownload(Url、dest和“c.zip”)
Debug.Print“C take:”&EndTimer&“毫秒”
调试。打印“前置事件”
多芬特
调试。打印“Post DoEvents”
Debug.Print(“做工作”)
呼叫栏
调试。打印“前置事件”
多芬特
调试。打印“Post DoEvents”
调用FinishDownload(a、dest和“a.zip”)
Debug.Print(“完成”)
调用FinishDownload(b、dest和“b.zip”)
调试。打印(“b完成”)
调用FinishDownload(c、dest和“c.zip”)
调试打印(“c完成”)
端函数
函数下载_文件(ByVal vWebFile作为字符串,ByVal vLocalFile作为字符串)作为布尔值
Dim-oXMLHTTP作为对象,i作为长,vFF作为长,oResp()作为字节
'您还可以将引用设置为Microsoft XML,并将oXMLHTTP设置为MSXML2.XMLHTTP
设置oXMLHTTP=CreateObject(“MSXML2.XMLHTTP”)
打开“GET”,vWebFile,False“打开套接字以获取网站
oXMLHTTP.send“发送请求
'等待请求完成
执行oXMLHTTP.readyState 4时
多芬特
环
oResp=oXMLHTTP.responseBody'将结果作为字节数组返回
'创建本地文件并将结果保存到其中
vFF=自由文件
如果Dir(vLocalFile)“,则杀死vLocalFile
打开二进制文件作为#vFF的vLocalFile
放#vFF,oResp
关闭#vFF
“清除内存
设置oXMLHTTP=Nothing
端函数
子栏()
作为整数的Dim F
F=自由文件
打开“C:\sandbox\”&“\example.txt”作为F输出
关闭#F
端接头
专用子工作簿\u窗口大小调整(ByVal Wn作为窗口)
调试。打印“工作簿\u窗口大小调整”
端接头
来自@Tim Williams在我创建的评论中提供的链接,它很有效
Function StartDownload(ByVal vWebFile As String) As Object
Dim oXMLHTTP As Object, i As Long, vFF As Long, oResp() As Byte
'You can also set a ref. to Microsoft XML, and Dim oXMLHTTP as MSXML2.XMLHTTP
Set oXMLHTTP = CreateObject("MSXML2.XMLHTTP")
oXMLHTTP.Open "GET", vWebFile, True'Open socket to get the website
oXMLHTTP.Send 'send request
Set StartDownload = oXMLHTTP
End Function
Sub FinishDownload(ByRef oXMLHTTP, ByVal vLocalFile As String)
'Wait for request to finish
Do While oXMLHTTP.readyState <> 4
DoEvents
Loop
oResp = oXMLHTTP.responseBody 'Returns the results as a byte array
'Create local file and save results to it
vFF = FreeFile
If Dir(vLocalFile) <> "" Then Kill vLocalFile
Open vLocalFile For Binary As #vFF
Put #vFF, , oResp
Close #vFF
'Clear memory
Set oXMLHTTP = Nothing
End Sub
Function foo()
Dim dest As String
dest = "C:\sandbox\"
url = "http://ipv4.download.thinkbroadband.com/200MB.zip"
Dim a, b, c As Object
DoEvents
Set a = DownloadManager.StartDownload(url)
DoEvents
Set b = DownloadManager.StartDownload(url)
DoEvents
Set c = DownloadManager.StartDownload(url)
DoEvents
Debug.Print ("Do Something")
Call FinishDownload(a, dest & "a.zip")
Debug.Print ("a done")
Call FinishDownload(b, dest & "b.zip")
Debug.Print ("b done")
Call FinishDownload(c, dest & "c.zip")
Debug.Print ("c done")
End Function
函数StartDownload(ByVal vWebFile作为字符串)作为对象
Dim-oXMLHTTP作为对象,i作为长,vFF作为长,oResp()作为字节
'您还可以将引用设置为Microsoft XML,并将oXMLHTTP设置为MSXML2.XMLHTTP
设置oXMLHTTP=CreateObject(“MSXML2.XM