VBA如果<object>是Nothing

我想testing一个对象,看它是否不存在。 如果它不存在,我只想显示一个MsgBox(或者在单元格A1中写入错误)。 香蕉不存在于这个XML中。

<?xml version="1.0"?> <catalog> <book id="Adventure"> <author>Gambardella, Matthew</author> <title>XML Developer's Guide</title> <price>44.95</price> </book> <book id="Adventure"> <author>Ralls, Kim</author> <title>Midnight Rain</title> <price>5.95</price> </book> <book id="Adventure"> <author>Boal, John</author> <title>Mist</title> <price>15.95</price> </book> <book id="Mystery"> <author>Ralls, Kim</author> <title>Some Mystery Book</title> <price>9.95</price> </book> </catalog> 

testing代码:

 Sub mySub() Dim XMLFile As Variant Dim Author As Object Dim athr As String, BookType As String, Title As String, StoreLocation As String Dim AuthorArray() As String, BookTypeArray() As String, TitleArray() As String, StoreLocationArray() As String Dim i As Long, x As Long, j As Long, pn As Object, loc As Object, arr, ln As String, loc2 As Object Dim mainWorkBook As Workbook Dim n As IXMLDOMNode Set mainWorkBook = ActiveWorkbook Set XMLFile = CreateObject("Microsoft.XMLDOM") XMLFile.Load ("C:\BooksOriginal.xml") x = 1 j = 0 Set Author = XMLFile.SelectNodes("/catalog/book/banana") If Author Is Nothing Then MsgBox ("Not Found") Range("A1").Value = "Not found" End If If Not Author Is Nothing Then For i = 0 To (Author.Length - 1) athr = Author(i).Text If athr = "Ralls, Kim" Then Set pn = Author(i).ParentNode BookType = pn.getAttribute("id") Title = pn.getElementsByTagName("title").Item(0).nodeTypedValue AddValue AuthorArray, athr AddValue BookTypeArray, BookType AddValue TitleArray, Title AddValue StoreLocationArray, StoreLocation j = j + 1 x = x + 1 End If Next Range("A3").Resize(j, 1).Value = WorksheetFunction.Transpose(AuthorArray) Range("B3").Resize(j, 1).Value = WorksheetFunction.Transpose(BookTypeArray) End If End Sub 'Utility method - resize an array as needed, and add a new value Sub AddValue(arr, v) Dim i As Long i = -1 On Error Resume Next i = UBound(arr) + 1 On Error GoTo 0 If i = -1 Then i = 0 ReDim Preserve arr(0 To i) arr(i) = v End Sub 

为什么这个块不做任何事情? 我感觉VBA完全忽略了它。 我甚至尝试在If语句中joinEnd。

 If Author Is Nothing Then MsgBox ("Not Found") Range("A1").Value = "Not found" End End If 

此外,该错误也是在打印范围线..这是在If Not Author Is Nothing语句。 很奇怪。

你的循环仍然执行的原因是, If Author Is Nothing评估为真。 对XMLFile.SelectNodes的调用返回一个IXMLDOMNodeList,它是一个可枚举的容器。 事实上,它可以用于For Each语法的原因取决于这个。 一般来说,函数返回的任何枚举都会给你一个没有任何项的枚举,而不是一个空对象。 For Each语法相当于这样做:

 Do While Author.NextNode() '... Loop 

…要么…

 For i = 0 To (Author.Length - 1) '... Next i 

对于每一个只是有更多的可读性的好处。

你得到的错误实际上与你提出的问题没有关系,如果你没有修正XMLFile.SelectNodes("/catalog/book/banana")的返回值的检查,得到任何结果。 错误在于试图在循环之后使用你的数组,如果它们没有被实例化(尽pipe添加的End会解决这个问题)。

当你退出循环,到这里…

 Range("A3").Resize(j, 1).Value = WorksheetFunction.Transpose(AuthorArray) Range("B3").Resize(j, 1).Value = WorksheetFunction.Transpose(BookTypeArray) 

…您的AuthorArray和BookTypeArray只有在经过循环后才被初始化,因为您依赖于Sub AddValue中的ReDim Preserve来初始化它们。 这有两个解决scheme。 你可以把Exit Sub放在你的返回值的testing中:

 If Author.Length = 0 Then MsgBox ("Not Found") Range("A1").Value = "Not found" Exit Sub End If 

或者你可以在函数的开头初始化数组。

 AuthorArray = Split(vbNullString) BookTypeArray = Split(vbNullString) 

这还有一个额外的好处,就是允许你跳过数组大小的所有环节来确定它们是否已经被初始化。 Split(vbNullString)将返回一个UBound为-1的数组( MyVariantArray = Array()将对Variant数组执行相同操作)。 这允许你像这样重写Sub AddValue:

 Sub AddValue(arr, v) ReDim Preserve arr(UBound(arr) + 1) arr(UBound(arr)) = v End Sub 

最后,我会采取@ SOofXWLS的build议和@ barrowc的build议,并使用显式对象types,因为你是迟到的绑定。 这样你的智能感知至less会显示自动完成列表。 如果你不知道返回什么types的对象,只需按下F2对象浏览器,并检查:

在对象浏览器窗口中选择节点

如果你不知道从哪里开始新的对象模型,你也可以使用这个快速和肮脏的技巧…

 Dim XMLFile As Object Set XMLFile = CreateObject("Microsoft.XMLDOM") Debug.Print TypeName(XMLFile) 'DOMDocument 

… 接着…

 Dim XMLFile As DOMDocument