You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Excel VBA运行时错误91无法解决:XML拉取天气数据脚本报错

解决VBA XML拉取天气数据时的运行时错误91(Object variable not set)

我来帮你排查这个问题——虽然你觉得wshape已经设置好了,但运行时错误91的根源其实不在它身上,而是出在XML节点获取失败上。这个错误本质是你尝试访问一个未初始化的对象引用,下面是几个最可能的触发点,以及对应的修复方案:

可能的错误原因

  • XML响应加载失败:resp.LoadXML req.responseText可能没成功加载XML(比如API密钥无效返回错误页面、网络问题导致响应异常),这会让resp.getElementsByTagName("weather")返回空集合,后续访问节点的Text属性自然会报错。
  • 节点路径或命名空间问题:有些API返回的XML带有命名空间,直接用getElementsByTagName或SelectNodes可能找不到目标节点;或者你写的节点名称和实际XML里的结构不一致(比如weatherIconUrl的层级不对,或者拼写错误)。
  • SelectNodes返回空集合:比如weather.SelectNodes("weatherIconUrl")没找到任何节点,这时Item(0)就是Nothing,访问它的.Text就会直接触发错误91。

修复后的代码(带错误检查)

我给你调整了代码,添加了请求状态验证、XML加载检查、节点存在性判断,还加了旧图标清理的逻辑,避免重复创建形状:

Option Explicit
Private Sub btnRefresh_Click()
    Dim req As New MSXML2.XMLHTTP.6.0 ' 使用新版XMLHTTP提升兼容性
    Dim resp As New MSXML2.DOMDocument60
    Dim weather As IXMLDOMNode
    Dim ws As Worksheet: Set ws = ActiveSheet
    Dim wshape As Shape
    Dim thiscell As Range
    Dim i As Integer
    Dim weatherIconNode As IXMLDOMNode
    
    ' 先清理之前生成的天气图标,避免重复堆积
    For Each wshape In ws.Shapes
        If Not Intersect(wshape.TopLeftCell, ws.Range("weatherPicture")) Is Nothing Then
            wshape.Delete
        End If
    Next wshape
    
    ' 发送同步请求(显式设置False确保请求完成再执行后续代码)
    req.Open "GET", "http://api.worldweatheronline.com/premium/v1/weather.ashx?key=myConfidentialToken&q=Baku&format=xml&num_of_days=5", False
    req.send
    
    ' 检查请求是否成功
    If req.Status <> 200 Then
        MsgBox "请求失败,状态码:" & req.Status & vbCrLf & req.responseText
        Exit Sub
    End If
    
    ' 加载XML并检查是否成功
    resp.async = False
    If Not resp.LoadXML(req.responseText) Then
        MsgBox "XML解析失败:" & resp.parseError.reason & vbCrLf & resp.parseError.srcText
        Exit Sub
    End If
    
    ' 遍历每个weather节点
    For Each weather In resp.getElementsByTagName("weather")
        i = i + 1
        
        ' 日期节点检查
        If weather.SelectNodes("date").Length > 0 Then
            ws.Range("theDate").Cells(1, i).Value = weather.SelectNodes("date")(0).Text
        End If
        
        ' 最高温节点检查
        If weather.SelectNodes("maxtempC").Length > 0 Then
            ws.Range("highTemps").Cells(1, i).Value = weather.SelectNodes("maxtempC")(0).Text
        End If
        
        ' 最低温节点检查
        If weather.SelectNodes("mintempC").Length > 0 Then
            ws.Range("lowTemps").Cells(1, i).Value = weather.SelectNodes("mintempC")(0).Text
        End If
        
        ' 天气图标节点检查(这就是你之前报错的关键位置)
        Set weatherIconNode = weather.SelectNodes("weatherIconUrl").Item(0)
        If Not weatherIconNode Is Nothing Then
            Set thiscell = ws.Range("weatherPicture").Cells(1, i)
            Set wshape = ws.Shapes.AddShape(msoShapeRectangle, thiscell.Left, thiscell.Top, thiscell.Width, thiscell.Height)
            wshape.Fill.UserPicture weatherIconNode.Text
        End If
    Next weather
End Sub

额外调试技巧

  • 查看API返回的原始内容:在req.send后添加Debug.Print req.responseText,然后打开VBA的立即窗口(Ctrl+G),就能看到实际返回的XML,确认节点名称和结构是否符合你的预期。
  • 验证API密钥:如果密钥无效,API会返回错误信息,通过上面的MsgBox就能看到具体错误。
  • 命名空间处理:如果返回的XML带有命名空间(比如根节点有xmlns="xxx"),你需要给DOMDocument设置命名空间前缀才能正确获取节点,比如:
    resp.SetProperty "SelectionNamespaces", "xmlns:ww='http://api.worldweatheronline.com/premium/v1'"
    
    之后用weather.SelectNodes("ww:weatherIconUrl")来获取节点。

内容的提问来源于stack exchange,提问作者Elgin Cahangirov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:25:57