VBA 使用 Internet Explorer 导航时出错
VBA error when navigating with Internet Explorer
我正在尝试从 Nationwide 下载专有 investments/positions/pricing 的 table。该代码似乎可以满足我的要求,除了在我尝试 select 特定帐户(单击)
时产生 "object required" 错误
我以为我有正确的代码告诉我的宏等待 IE 准备好继续,但显然我遗漏了一些东西。
在代码中,相关行被突出显示。如果我在错误行上方输入 STOP,我可以等到 "see" link 出现,然后 "continue" 代码并按预期运行。
因为这是我的财务账户,所以我无法提供用户名和密码来让别人复制确切的问题,但这是代码、错误消息和突出显示。赞赏建议。
Option Explicit
'set Reference to Microsoft Internet Controls
Sub DownLoadFunds()
Dim IE As InternetExplorer
Dim sHTML
Const sURL As String = "https://www.nationwide.com/access/web/login.htm"
Const sURL2 As String = "https://isc.nwservicecenter.com/iApp/isc/app/ia/balanceDetail.do?basho.menuNodeId=12245"
Dim wsTemp As Worksheet
Set wsTemp = Worksheets("Scratch")
Set IE = New InternetExplorer
With IE
.Navigate sURL
.Visible = True 'for debugging
Do While .ReadyState <> READYSTATE_COMPLETE
DoEvents
Loop
Do While .Busy = True
DoEvents
Loop
'Login: User Name and Password "remembered" by IE
.Document.all("submitButton").Click
Do While .ReadyState <> READYSTATE_COMPLETE
DoEvents
Loop
Do While .Busy = True
DoEvents
Loop
'Select this account to show
.Document.all("RothIRA_#########").Click '<--Error at this line
Do While .ReadyState <> READYSTATE_COMPLETE
DoEvents
Loop
Do While .Busy = True
DoEvents
Loop
.Navigate sURL2
Do While .ReadyState <> READYSTATE_COMPLETE
DoEvents
Loop
Do While .Busy = True
DoEvents
Loop
Set sHTML = .Document.GetElementByID("fundByFundOnly")
With wsTemp
.Cells.Clear
.Range("a2") = sHTML.innertext
End With
.Quit
End With
Set IE = Nothing
End Sub
这是错误信息:
这显示了突出显示的行:
编辑:
根据 Tim Williams 的建议,我添加了一个循环来测试所需元素是否存在。这似乎有效:
...
On Error Resume Next
Do
Err.Clear
DoEvents
Application.Wait (Time + TimeSerial(0, 0, 1))
.Document.getelementbyid("RothIRA_#########").Click
Loop Until Err.Number = 0
On Error GoTo 0
....
IE.Document.all("#RothIRA_....")
正在返回 Nothing
(null
在更精炼的语言中),因此调用 Click
方法会导致错误。
您的代码与执行此操作相同:
Dim rothElement As Whatever
rothElement = IE.Document.all("#RothIRA_....")
rothElement.Click
...什么时候应该这样做:
Dim rothElement As Whatever
rothElement = IE.Document.all("#RothIRA_....")
If rothElement <> Nothing Then
rothElement.Click
End If
我建议使用现代 document.GetElementById
方法而不是已弃用的方法(如果不是过时的话)document.All
API.
possible/likely 页面正在使用脚本动态加载某些内容或生成某些布局在您的 "wait" 循环完成后。该循环只等到所有链接 content/resources 都已加载 - 它不会等待加载页面上的脚本完成等
一种方法是让代码循环等待渲染所需的元素:
Const MAX_WAIT_SEC as Long = 5 'limit on how long to wait...
Dim t
t = Timer
Do While .Document.all("RothIRA_#########") Is Nothing
DoEvents
'or you can Sleep here
If Timer - t > MAX_WAIT_SEC Then Exit Do
Loop
'carry on...
我正在尝试从 Nationwide 下载专有 investments/positions/pricing 的 table。该代码似乎可以满足我的要求,除了在我尝试 select 特定帐户(单击)
时产生 "object required" 错误我以为我有正确的代码告诉我的宏等待 IE 准备好继续,但显然我遗漏了一些东西。
在代码中,相关行被突出显示。如果我在错误行上方输入 STOP,我可以等到 "see" link 出现,然后 "continue" 代码并按预期运行。
因为这是我的财务账户,所以我无法提供用户名和密码来让别人复制确切的问题,但这是代码、错误消息和突出显示。赞赏建议。
Option Explicit
'set Reference to Microsoft Internet Controls
Sub DownLoadFunds()
Dim IE As InternetExplorer
Dim sHTML
Const sURL As String = "https://www.nationwide.com/access/web/login.htm"
Const sURL2 As String = "https://isc.nwservicecenter.com/iApp/isc/app/ia/balanceDetail.do?basho.menuNodeId=12245"
Dim wsTemp As Worksheet
Set wsTemp = Worksheets("Scratch")
Set IE = New InternetExplorer
With IE
.Navigate sURL
.Visible = True 'for debugging
Do While .ReadyState <> READYSTATE_COMPLETE
DoEvents
Loop
Do While .Busy = True
DoEvents
Loop
'Login: User Name and Password "remembered" by IE
.Document.all("submitButton").Click
Do While .ReadyState <> READYSTATE_COMPLETE
DoEvents
Loop
Do While .Busy = True
DoEvents
Loop
'Select this account to show
.Document.all("RothIRA_#########").Click '<--Error at this line
Do While .ReadyState <> READYSTATE_COMPLETE
DoEvents
Loop
Do While .Busy = True
DoEvents
Loop
.Navigate sURL2
Do While .ReadyState <> READYSTATE_COMPLETE
DoEvents
Loop
Do While .Busy = True
DoEvents
Loop
Set sHTML = .Document.GetElementByID("fundByFundOnly")
With wsTemp
.Cells.Clear
.Range("a2") = sHTML.innertext
End With
.Quit
End With
Set IE = Nothing
End Sub
这是错误信息:
这显示了突出显示的行:
编辑:
根据 Tim Williams 的建议,我添加了一个循环来测试所需元素是否存在。这似乎有效:
...
On Error Resume Next
Do
Err.Clear
DoEvents
Application.Wait (Time + TimeSerial(0, 0, 1))
.Document.getelementbyid("RothIRA_#########").Click
Loop Until Err.Number = 0
On Error GoTo 0
....
IE.Document.all("#RothIRA_....")
正在返回 Nothing
(null
在更精炼的语言中),因此调用 Click
方法会导致错误。
您的代码与执行此操作相同:
Dim rothElement As Whatever
rothElement = IE.Document.all("#RothIRA_....")
rothElement.Click
...什么时候应该这样做:
Dim rothElement As Whatever
rothElement = IE.Document.all("#RothIRA_....")
If rothElement <> Nothing Then
rothElement.Click
End If
我建议使用现代 document.GetElementById
方法而不是已弃用的方法(如果不是过时的话)document.All
API.
possible/likely 页面正在使用脚本动态加载某些内容或生成某些布局在您的 "wait" 循环完成后。该循环只等到所有链接 content/resources 都已加载 - 它不会等待加载页面上的脚本完成等
一种方法是让代码循环等待渲染所需的元素:
Const MAX_WAIT_SEC as Long = 5 'limit on how long to wait...
Dim t
t = Timer
Do While .Document.all("RothIRA_#########") Is Nothing
DoEvents
'or you can Sleep here
If Timer - t > MAX_WAIT_SEC Then Exit Do
Loop
'carry on...