- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
情况:
我正在尝试检查变量 a
,在本地窗口中显示为 DispStaticNodeList
对象;每次我尝试执行此操作时,Excel 都会崩溃。
这是本地窗口中的变量 a
,显然是 DispStaticNodeList
类型:
重现 Excel 崩溃:
For Each
循环它也会导致崩溃。*TestFail研究亮点:
Excel
+ Crash
+ DispStaticNodeList
之类的组合,结果为零;至少我使用的谷歌搜索词是这样。很确定我的 Google-Fu 很弱。如果我相信这个article我正在处理 MSHTML
支持的 COM 对象。
并根据this :
If the name is DispStaticNodeList, we can be pretty sure it's an array..(or at least has array semantics).
基于第 3 点,我编写了下面的代码 TestPass
,它确实成功地循环了它,但我不完全理解为什么。我已经设置了一个对象,然后循环了它的 len!
NodeList objects are collections of nodes such as those returned by properties such as Node.childNodes and the document.querySelectorAll() method.
所以看起来这个对象可能是一个 NodeList
,它给出了即时窗口中的描述似乎是正确的,并且作为一个列表我可以遍历它的长度,但不确定为什么 For Each
不起作用以及 Excel 崩溃的原因。同事建议它可能由于数据的分层性质而崩溃。我还注意到有一些名为 IDOMNodeIterator
和 NodeIterator
的类,但我不确定是否可以按照 NodeList
的描述使用它们方法 here .
问题:
什么是 a
?为什么它会在尝试使用 For Each
检查或循环时导致 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
注意事项:
我向一位同事发送了一份测试工作簿,他也能够通过给定的示例重现此行为。
项目引用:
HTML 示例(还提供了链接)
<div class="noSel">
<h1 style=""><span class="markup"><h1></span>Welcome to My Homepage<span class="markup"></h1></span></h1>
<div id="helpIntro" style="">
<span class="markup"><div class="intro"></span>
<div class="intro">
<p style="margin-top: 4px; border-color: rgb(255, 102, 102); background-color: rgb(255, 255, 153);"><span class="markup"><p></span>My name is Donald <span id="Lastname" style=""><span class="markup"><span id="Lastname"></span>Duck.<span class="markup"></span></span></span><span class="markup"></p></span></p>
<p id="my-Address" style="border-color: rgb(255, 102, 102); background-color: rgb(255, 255, 153);"><span class="markup"><p id="my-Address"></span>I live in Duckburg<span class="markup"></p></span></p>
<p style="margin-bottom: 4px; border-color: rgb(255, 102, 102); background-color: rgb(255, 255, 153);"><span class="markup"><p></span>I have many friends:<span class="markup"></p></span></p>
</div>
<span class="markup"></div></span>
</div>
<br>
<div class="helpUl">
<span class="markup"><ul id="Listfriends></span>
<ul id="Listfriends" style="margin-top:0px;margin-bottom:0px;">
<li><span class="markup"><li></span>Goofy<span class="markup"></li></span></li>
<li><span class="markup"><li></span>Mickey<span class="markup"></li></span></li>
<li><span class="markup"><li></span>Daisy<span class="markup"></li></span></li>
<li><span class="markup"><li></span>Pluto<span class="markup"></li></span></li>
</ul>
<span class="markup"></ul></span>
</div>
<ul style="display:none;"></ul>
<p style=""><span class="markup"><p></span>All my friends are great!<span class="markup"><br></span><br>But I really like Daisy!!<span class="markup"></p></span></p>
<p lang="it" title="Hello beautiful" style=""><span class="markup"><p lang="it" title="Hello beautiful"></span>Ciao bella<span class="markup"></p></span></p>
编辑:我也能够以下列方式循环:
Public Sub Test()
Dim html As MSHTML.HTMLDocument, i As Long
Set html = GetTestHTML
For i = 0 To html.querySelectorAll("div.intro p").Length - 1
Debug.Print html.querySelectorAll("div.intro p")(i).innerText
Next i
End Sub
最佳答案
If the name is DispStaticNodeList, we can be pretty sure it's an array..(or at least has array semantics).
数组可以通常用For Each
循环迭代,但是it's more efficient使用 For
循环迭代它们。看起来你得到的不是完全数组,虽然它似乎支持索引,但显然不支持枚举,这可以解释爆炸当您尝试使用 For Each
循环枚举它时。
看起来 locals 工具窗口可能正在使用 For Each
语义来列出集合中的项目。
我不熟悉那个特定的库,所以这是一些(受过教育的)猜测,但是制作一个不能用 For Each
迭代的自定义 COM 集合类型非常容易> 在 VBA 中循环 - 通常错误是在 VBA 端捕获的......似乎库的枚举器实现中可能存在错误(假设它有一个枚举器)导致它抛出一个异常,最终未处理并以某种方式需要一切都结束了...问题是,您无法修复并重新编译该库...所以您唯一能做的就是避免使用 For Each
循环迭代该类型,并避免在 locals 工具窗口中展开它(因此,...经常保存您的工作!)。
This article从 C#/.NET 的角度给出了 COM 枚举如何工作的好主意。当然,该库不是托管代码 (.NET),但所使用的 COM 概念是相同的。
TL;DR:并不是因为您可以 For...Next
才可以 For Each
;涉及的 COM 类型必须明确支持枚举。如果 VBA 代码使用 For Each
循环编译,那么它确实如此,因此它一定是类型枚举器中的错误。
关于html - 尝试检查 DispStaticNodeList 时 Excel 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50021133/
情况: 我正在尝试检查变量 a,在本地窗口中显示为 DispStaticNodeList 对象;每次我尝试执行此操作时,Excel 都会崩溃。 这是本地窗口中的变量 a,显然是 DispStaticN
我是一名优秀的程序员,十分优秀!