我得到了一个代码,从一个需要凭据的网站下载CSV文件。我得到了一个代码,感谢这个网站,我可以适应我的需要。我的代码的相关部分是:
Option Explicit
Private Declare Function URLDownloadToFileA Lib "urlmon" _
(ByVal pCaller As Long, _
ByVal szURL As String, _
ByVal szFileName As String, _
ByVal dwReserved As Long, _
ByVal lpfnCB As Long) As Long
Private Function DownloadUrlFile(URL As String, LocalFilename As String) As Boolean
Dim RetVal As Long
RetVal = URLDownloadToFileA(0, URL, LocalFilename, 0, 0)
If RetVal = 0 Then DownloadUrlFile = True
End Function
Sub DESCARGAR_CSV_DATOS()
Dim EstaURL As String
Dim EsteCSV As String
EstaURL = "https://user:token@www.privatewebsite.com/export/targetfile.csv"
EsteCSV = "MyCSV " & Format(Date, "dd-mm-yyyy") & ".csv"
With Application
.DisplayAlerts = False
.ScreenUpdating = False
End With
DownloadUrlFile EstaURL, _
ThisWorkbook.Path & "\" & EsteCSV
DoEvents
Workbooks.Open ThisWorkbook.Path & "\" & EsteCSV, , True, , , , , , , , , , , True
'rest is just doing operations and calculations inside workbook
End Sub
对不起,但我不能提供真实的的URL。无论如何,这段代码自2019年9月以来一直完美地工作。而且它每天都在完美地工作。
执行此代码的计算机都是Windows 7和Excel 2007和64位。没有一台失败。
但现在,这项任务要外包给另一个办公室,在那里,电脑是Excel 2019,Windows 10和64位。
代码在那里不起作用,没有出现任何错误,但函数DownloadUrlFile
在Excel 2019 + W10上没有下载任何文件
所以恢复,Excel 2007 + Windows 7完美工作(今天测试)。Excel 2019 + Windows 10不工作(屏幕上没有错误)。
我试着去弥补的事情:
1.我已经检查了文件urlmon.dll
是否存在于system32
中,它确实存在
1.我尝试使用PtrSafe
声明函数URLDownloadToFileA
1.如果我在装有Excel 2019 + W10的PC中手动输入Chrome中的URL,则文件会正确下载,因此URL是可以的。
这些都没有解决我的问题。我很确定解决方案真的很简单,因为代码在Excel 2007中运行得很好,但我找不到我在这里遗漏的东西。
我想得到一个在任何情况下都能工作的代码,但如果这是唯一的方法,我也会接受一个只在Excel 2019和Windows 10中工作的解决方案。
希望有人能对此提出一些看法。提前感谢。
UPDATE:也尝试了this post中的解决方案,但仍然没有任何结果。
**更新2:**此外,使用Excel 2010测试了这里发布的代码(Excel 2007),它工作得很好。
**UPDATE 3:**变量RetVal
存储下载的结果。我知道一些值:
' Returns 0 if success, error code if not.
' Error codes:
' -2146697210 "file not found".
' -2146697211 "domain not found".
' -2147467260 "transfer aborted".
但在我的例子中,它返回-2147221020
,那会是什么呢?
**更新4:**好吧,这只是奇怪。我已经尝试了相同的代码从公共网站下载不同的文件,它在Excel 2019 + W10中工作。我做了一个新的简单代码,如下所示:
#If VBA7 And Win64 Then
Private Declare PtrSafe Function URLDownloadToFile Lib "urlmon" _
Alias "URLDownloadToFileA" ( _
ByVal pCaller As LongPtr, _
ByVal szURL As String, _
ByVal szFileName As String, _
ByVal dwReserved As LongPtr, _
ByVal lpfnCB As LongPtr _
) As Long
#Else
Private Declare Function URLDownloadToFile Lib "urlmon" _
Alias "URLDownloadToFileA" ( _
ByVal pCaller As Long, _
ByVal szURL As String, _
ByVal szFileName As String, _
ByVal dwReserved As Long, _
ByVal lpfnCB As Long _
) As Long
#End If
Sub Descarga()
Dim EstaURL As String
Dim EsteCSV As String
EstaURL = privateone 'can't be shared, sorry
EsteCSV = "CSV Datos " & Format(Date, "dd-mm-yyyy") & ".csv"
On Error GoTo Errores
URLDownloadToFile 0, "https://tutorialesexcel.com/wp-content/uploads/2018/10/funciones.xlsm", ThisWorkbook.Path & "\" & EsteCSV, 0, 0
URLDownloadToFile 0, EstaURL, ThisWorkbook.Path & "\" & EsteCSV, 0, 0
Exit Sub
Errores:
'Si es un bucle lo mejor sería no mostrar ningún mensaje
MsgBox "Not downloaded", vbCritical, "Errores"
End Sub
显示URLDownloadToFile 0, "https://tutorialesexcel.com/wp-content/uploads/2018/10/funciones.xlsm", ThisWorkbook.Path & "\" & EsteCSV, 0,
的行可以完美运行并下载文件。
行URLDownloadToFile 0, EstaURL, ThisWorkbook.Path & "\" & EsteCSV, 0, 0
不起作用。
因此,再次测试了完全相同的代码,但在Excel 2007和他们都工作
为什么第一个下载可以在Excel 2019 + W10上工作,而第二个不能在Excel 2007+W7上工作?
**UPDATE 5:**该URL是私有的,因为它包含用户名和密码,但它是这样的:
https://user:token@www.privatewebsite.com/export/target%20file.csv
感谢@Stachu,该URL在任何PC上的Internet Explorer上都无法手动工作(我的意思是在资源管理器导航栏中复制/粘贴)。该URL在所有PC上的Google Chrome中都可以完美工作。
这真的很奇怪,手动,在Internet Explorer上的URL不工作,但与VBA编码和Excel2007/2010上执行相同的URL完美的作品.也许我应该改变一些关于编码?
**更新6:**还在研究你的所有帖子。问题是我只是一个数据分析师,所以这里发布的大量信息对我来说听起来真的很难。
一天前我已经把所有的信息通过电子邮件发给了IT人员,现在还在等待答复。
与此同时,基于这里的信息,终于编写了一个完全不同的东西,适用于所有机器。它适用于Windows 7和10,Excel 2007和2010(安装为32位)和Excel 2019(安装为64位)。
我在这里添加代码,所以也许有人可以解释为什么它工作正常,但看起来问题是base64编码。
我现在得到的代码是这样的(添加了对Microsoft Winhttp Setvices 5.1的引用)
Application.ScreenUpdating = False
Dim whr As WinHttp.WinHttpRequest
Dim oStream As Object
Dim EsteCSV As String
Dim EstaURL As String
EstaURL = "https://user:pass@www.privatewebsite.com/export/target%20file.csv"
EsteCSV = "CSV Datos" & Format(Date, "dd-mm-yyyy") & ".csv"
'Set whr = CreateObject("WinHttp.WinHttpRequest.5.1")
Set whr = New WinHttp.WinHttpRequest
whr.Open "GET", EstaURL, True
whr.setRequestHeader "Authorization", "Basic " & EncodeBase64("user" & ":" & "password")
whr.send
' Using 'true' above and the call below allows the script to remain responsive.
whr.waitForResponse
DoEvents
Set oStream = CreateObject("ADODB.Stream")
oStream.Open
oStream.Type = 1
oStream.Write whr.responseBody
oStream.SaveToFile ThisWorkbook.Path & "\" & EsteCSV
oStream.Close
DoEvents
Set oStream = Nothing
whr.abort
Set whr = Nothing
'rest of code for operations
Kill ThisWorkbook.Path & "\" & EsteCSV
Application.ScreenUpdating = True
End Sub
Private Function EncodeBase64(text As String) As String
Dim arrData() As Byte
arrData = StrConv(text, vbFromUnicode)
Dim objXML As Object
Dim objNode As Object
Set objXML = CreateObject("MSXML2.DOMDocument")
Set objNode = objXML.createElement("b64")
objNode.DataType = "bin.base64"
objNode.nodeTypedValue = arrData
EncodeBase64 = objNode.text
Set objNode = Nothing
Set objXML = Nothing
End Function
7条答案
按热度按时间3bygqnnd1#
子代码是好的。检查工具菜单中的引用在vba和作出声明ptrsafe如下
t3psigkw2#
执行此代码的计算机都是Windows 7和Excel 2007和64位。没有一台失败。
但现在,这项任务要外包给另一个办公室,在那里,电脑是Excel 2019,Windows 10和64位。
代码在那里不起作用,没有出现任何错误,但是函数DownloadUrlFile在Excel 2019 + W10上没有下载任何文件
我猜在另一间办公室也不行。
只有当URL为私有且IP未加入白名单时才会出现这种情况,您可以咨询您的网络团队,他们是否已将该URL的IP加入白名单。
URLDownloadToFile 0,“https://tutorialesexcel.com/wp-content/uploads/2018/10/funciones.xlsm“,ThisWorkbook.Path &“\”& EsteCSV,0这一行可以完美地工作并下载该文件。
行URLDownloadToFile 0,EstaURL,ThisWorkbook.Path &“\”& EsteCSV,0,0不起作用。
因此,再次测试完全相同的代码,但在Excel2007和他们都工作
为什么第一个下载可以在Excel 2019 + W10上工作,而第二个不能在Excel 2007+W7上工作?
此外,同样的代码对公共URL工作得很好,而对私有URL却没有,除非有IP限制。
cidc1ykv3#
至于你的错误,-2147221020 =〉0x 800401 E4根据VBA Error Codes and Descriptions,这个错误是MK_E_SYNTAX,它是'无效的名字语法'。
当它说名字,我猜这意味着你的网址,老实说,网址看起来语法不正确...
"https://user:token@www.privatewebsite.com/export/targetfile.csv"
我不得不四处挖掘,看看这是否真的符合网址的网络标准。同时,我建议找出一个不同的网址。它可能是一个升级到urlmon.dll现在抱怨的网址,而Windows 7版本没有。
好的,我的错,实际上看起来你可以做这样的URI,理论上,所以我有一个URI片段
first-client:noonewilleverguess@localhost:8080/oauth/token
取自OAuth2 Boot好吧,所以它是有效的,重新顶部的第17页rfc3986。
authority = [ userinfo "@" ] host [ ":" port ]
看起来你必须进入API调用来设置用户名和密码。
更新:祝贺你的解决方案,你邀请一个解释,也许看到这个MSDN Forum,其中的话语概述了不同的技术栈。如果我浏览C++头文件
urlmon.h
,那么URLDownloadToFile
看起来像是基于WinInet
的。所以切换到WinHTTP
是一个明智的举动,更多的基于服务器的堆栈。此外,在相同的堆栈逻辑上,我相信您可以使用MSXML2.ServerXMLHTTP(参见VBScript newsgroup archive)
efzxgjgh4#
我在Excel 2019 / O365 64位(版本:1912)/ win 10 64位
我知道你有一个工作守则,但如果其他人需要一个替代品,这里是:
qybjjes15#
您使用的“简化”方法(user+password@url)由于其潜在的远程滥用,充其量只能得到零星的支持。
例如,
...admin:admin@192.168.1.1/cgi-bin/something-else?...
的HREF链路足以利用仅由“拒绝远程访问”默认值而不是可靠密码保护的几个路由器,并且有很多这样的路由器。您可能能够通过在Internet Explorer中保存用户名和密码来克服这个问题,Excel使用Internet Explorer的库,和/或将远程站点放在Internet选项中的“受信任的站点”组中。但这也是一种权宜之计,因为密码缓存可能会被意外删除,安全级别可能会在任何时候被更新重置(我不止一次遇到这种情况)。
Here还有其他讨论的方法。否则,你的解决方案当然有效(你可能想要添加一个答案来达到这个效果,并将其标记为接受,以备下一个遇到同样问题的人使用)。
gcuhipw96#
我为此挣扎了好几天,直到我发现它可以在PowerShell的一行中完成,例如:
我想纯粹用VBA来做,但它运行了几页,让我失去了理智,所以每次我想下载文件时,我都从VBA调用PowerShell脚本。
非常,非常简单,“UseDefaultCredentials”绝对是一种享受,我不必担心登录到远程站点等。
这使我可以用几行代码将报告以PDF格式从SSRS下载到一个文件夹中。
33qvvth17#
感谢大家的帮助和回答。不幸的是,我的IT部门无法告诉我到底发生了什么,即使这里提供了很多有用的信息。
我在这里发布我们现在正在使用的代码。它在Excel 2007 32位,Excel 2010 32和64位以及Excel 2019 64位上完美工作。它在Windows 7和10上也可以工作。
为了使这段代码工作,你需要添加一个对
Microsoft Winhttp Setvices 5.1
的引用。如果你不知道如何做,请检查How to Add an Object Library Reference in VBA:再次感谢大家。这是一个很棒的地方。