Html Excel在尝试检查DispStaticNodeList时崩溃
情况: 我试图检查变量Html Excel在尝试检查DispStaticNodeList时崩溃,html,excel,vba,dom,web-scraping,Html,Excel,Vba,Dom,Web Scraping,情况: 我试图检查变量a,该变量在“局部变量”窗口中显示为dispstationNodeList对象;每次我尝试这样做时,Excel都会崩溃 以下是局部变量窗口中的变量a,其类型显然为dispstationNodeList: 复制Excel崩溃: Option Explicit Public Sub TestPass() Dim html As HTMLDocument Set html = GetTestHTML Dim a As Object, b As Obje
a
,该变量在“局部变量”窗口中显示为dispstationNodeList
对象;每次我尝试这样做时,Excel都会崩溃
以下是局部变量窗口中的变量a
,其类型显然为dispstationNodeList
:
复制Excel崩溃:
Option Explicit
Public Sub TestPass()
Dim html As HTMLDocument
Set html = GetTestHTML
Dim a As Object, b As Object
Set a = html.querySelectorAll("div.intro p")
Dim i As Long
For i = 0 To Len(a) -1
On Error Resume Next
Debug.Print a(i).innerText '<== HTMLParaElement
On Error GoTo 0
Next i
End Sub
Public Function GetTestHTML(Optional ByVal url As String = "https://www.w3schools.com/cssref/trysel.asp") As HTMLDocument
Dim http As New XMLHTTP60
Dim html As New HTMLDocument
With http 'Set http = CreateObject("MSXML2.XMLHttp60")
.Open "GET", url, False
.send
html.body.innerHTML = .responseText
Set GetTestHTML = html
End With
End Function
Public Sub TestFail()
Dim html As HTMLDocument
Set html = GetTestHTML
Dim a As Object, b As Object
Set a = html.querySelectorAll("div.intro p")
For Each b In a
Next b
End Sub
,也会导致崩溃。*TestFail
Option Explicit
Public Sub TestPass()
Dim html As HTMLDocument
Set html = GetTestHTML
Dim a As Object, b As Object
Set a = html.querySelectorAll("div.intro p")
Dim i As Long
For i = 0 To Len(a) -1
On Error Resume Next
Debug.Print a(i).innerText '<== HTMLParaElement
On Error GoTo 0
Next i
End Sub
Public Function GetTestHTML(Optional ByVal url As String = "https://www.w3schools.com/cssref/trysel.asp") As HTMLDocument
Dim http As New XMLHTTP60
Dim html As New HTMLDocument
With http 'Set http = CreateObject("MSXML2.XMLHttp60")
.Open "GET", url, False
.send
html.body.innerHTML = .responseText
Set GetTestHTML = html
End With
End Function
Public Sub TestFail()
Dim html As HTMLDocument
Set html = GetTestHTML
Dim a As Object, b As Object
Set a = html.querySelectorAll("div.intro p")
For Each b In a
Next b
End Sub
Excel
+Crash
+dispstationNodeList
之类的组合,结果为零;至少我用过谷歌搜索词。我很确定我的谷歌搜索引擎很弱MSHTML
支持的COM对象TestPass
,它确实成功地在上面循环,但我不完全理解为什么。我设置了一个对象,然后循环了它的len
节点列表
,在即时窗口中给出的描述似乎是正确的,作为一个列表,我可以循环它的长度,但不确定为什么每个的都不起作用,以及为什么Excel崩溃。他的同事建议,由于数据的层次性,它可能会崩溃。我进一步注意到有名为IDOMNodeIterator
和NodeIterator
的类,但我不确定是否可以按照NodeList
方法的描述使用这些类
问题:
Option Explicit
Public Sub TestPass()
Dim html As HTMLDocument
Set html = GetTestHTML
Dim a As Object, b As Object
Set a = html.querySelectorAll("div.intro p")
Dim i As Long
For i = 0 To Len(a) -1
On Error Resume Next
Debug.Print a(i).innerText '<== HTMLParaElement
On Error GoTo 0
Next i
End Sub
Public Function GetTestHTML(Optional ByVal url As String = "https://www.w3schools.com/cssref/trysel.asp") As HTMLDocument
Dim http As New XMLHTTP60
Dim html As New HTMLDocument
With http 'Set http = CreateObject("MSXML2.XMLHttp60")
.Open "GET", url, False
.send
html.body.innerHTML = .responseText
Set GetTestHTML = html
End With
End Function
Public Sub TestFail()
Dim html As HTMLDocument
Set html = GetTestHTML
Dim a As Object, b As Object
Set a = html.querySelectorAll("div.intro p")
For Each b In a
Next b
End Sub
什么是a
,当试图检查或循环每个的时,为什么会导致Excel崩溃
成功循环的代码:
Option Explicit
Public Sub TestPass()
Dim html As HTMLDocument
Set html = GetTestHTML
Dim a As Object, b As Object
Set a = html.querySelectorAll("div.intro p")
Dim i As Long
For i = 0 To Len(a) -1
On Error Resume Next
Debug.Print a(i).innerText '<== HTMLParaElement
On Error GoTo 0
Next i
End Sub
Public Function GetTestHTML(Optional ByVal url As String = "https://www.w3schools.com/cssref/trysel.asp") As HTMLDocument
Dim http As New XMLHTTP60
Dim html As New HTMLDocument
With http 'Set http = CreateObject("MSXML2.XMLHttp60")
.Open "GET", url, False
.send
html.body.innerHTML = .responseText
Set GetTestHTML = html
End With
End Function
Public Sub TestFail()
Dim html As HTMLDocument
Set html = GetTestHTML
Dim a As Object, b As Object
Set a = html.querySelectorAll("div.intro p")
For Each b In a
Next b
End Sub
注意事项:
我给一位同事发了一份测试手册,他也能用给出的例子重现这种行为
项目参考资料:
Option Explicit
Public Sub TestPass()
Dim html As HTMLDocument
Set html = GetTestHTML
Dim a As Object, b As Object
Set a = html.querySelectorAll("div.intro p")
Dim i As Long
For i = 0 To Len(a) -1
On Error Resume Next
Debug.Print a(i).innerText '<== HTMLParaElement
On Error GoTo 0
Next i
End Sub
Public Function GetTestHTML(Optional ByVal url As String = "https://www.w3schools.com/cssref/trysel.asp") As HTMLDocument
Dim http As New XMLHTTP60
Dim html As New HTMLDocument
With http 'Set http = CreateObject("MSXML2.XMLHttp60")
.Open "GET", url, False
.send
html.body.innerHTML = .responseText
Set GetTestHTML = html
End With
End Function
Public Sub TestFail()
Dim html As HTMLDocument
Set html = GetTestHTML
Dim a As Object, b As Object
Set a = html.querySelectorAll("div.intro p")
For Each b In a
Next b
End Sub
HTML示例(还提供了链接)
h1欢迎来到我的主页/h1
div class=“简介”
pMy的名字是Donald span id=“Lastname”Duck。/span/p
p id=“我的地址”style=“边框颜色:rgb(255,102,102);背景颜色:rgb(255,255,153)”>p id=“我的地址”我住在达克伯格/p
pI有很多朋友:/p
/div
ul id=“Listfriends
- 利古菲/李
- 利米奇/李
- Lidaysy/li
- 利普卢托/李
/保险商实验室
我的朋友们都很棒!但是我真的很喜欢黛西!!/p
p lang=“it”title=“Hello Beauty”再见贝拉/p
如果名称是dispstationNodeList,我们可以非常确定它是一个数组..(或者至少具有数组语义)
数组通常可以使用For Each
循环进行迭代,但是使用For
循环进行迭代。看起来您得到的并不完全是一个数组,虽然它似乎支持索引,但显然不支持枚举,这可以解释当您尝试使用For枚举数组时出现的问题r每个
循环
看起来“局部变量”工具窗口可能正在使用For Each
语义列出集合中的项
我不熟悉那个特定的库,所以这是一个有点(受过教育的)猜测,但是很容易创建一个自定义COM集合类型,它不能在VBA中用对每个循环进行迭代-通常错误是在VBA端捕获的…看起来库的枚举器实现中可能有错误(假设它有一个枚举器)导致它抛出一个异常,该异常最终未经处理,并以某种方式将所有内容都记录下来……问题是,您无法修复并重新编译该库……因此,您唯一能做的就是避免对每个
循环使用迭代该类型,并避免在“局部变量”工具窗口中扩展它(因此,…经常保存您的工作!)
从C#/.NET的角度给出了COM枚举如何工作的好主意。当然,该库不是托管代码(.NET),但使用的COM概念是相同的
TL;DR:并不是因为您可以为…Next
编写,所以您可以为每个编写;所涉及的COM类型必须明确支持枚举。如果VBA代码为每个循环编写,那么它确实支持,因此它一定是类型枚举器中的一个bug。让我想知道…考虑到早期绑定,RuberDuck是否能够加载that类型库?我记得有一些令人惊讶的问题(如果不是彻底崩溃,就会导致解析器失败)只是在其中一个XML或HTTP标准库中迭代类型和成员,但我不记得是否是该库。@MathieuGuindon感谢您的响应。请问您指的是哪个库?同事想知道这是否与分层数据有关。我猜应该是HTML库。无论定义哪个此dispstationNodeList
type;-)这与问题无关,但有一条(未经请求的)建议——始终对类型使用两部分命名。Dim html作为MSHTML.HTMLDocument