如何将 VARIANT 变量从一个子程序传递并转换为另一个子程序中的 OBJECT 变量?

How to pass & convert a VARIANT variable from one sub to an OBJECT variable in another sub?

我正在努力处理我的 VBA 代码。我有两个潜艇:

我的目标是从第一个 Sub (IEGetActivePage) 调用 VARIANT 变量 IE_Title 到下一个 Sub ( TestScrape2) 并将其转换为 OBJECT 变量(以便 TestScrape2 中的代码正常工作)。


编辑:


这是 IEGetActivePage 代码,带有 IE_Title 变量:

Option Explicit

Sub IEGetActivePage()

Dim marker As Variant  
Dim IE_Window As Variant
Dim IE_count As Variant
Dim X As Variant
Dim IE_Title As Variant   'The web page used in this code is the following: https://fr.wikipedia.org/wiki/Visual_Basic_for_Applications
Dim IE As Variant

marker = 0                                      
Set IE_Window = CreateObject("Shell.Application")
IE_count = IE_Window.Windows.Count                

For X = 0 To (IE_count - 1)               
    On Error GoTo ErrorHandler                    
    IE_Title = IE_Window.Windows(X).Document.Title
    If IE_Title Like "Visual Basic for Applications — Wikipédia" Then
        Set IE = Fenêtre.Windows(X)
        marker = 1
        Exit For
    Else
    End If
Next

If marker = 0 Then
    MsgBox ("The Internet window cannot be found")
Else
    AppActivate IE_Title 'Activates the correct Internet Explorer windows

'---Until there, the code works fine. The next step is an attempt to create a new variable out of the IE_Title variable and converting it to an object. As @Gustav suggested, I tried the SET function but I get the same result---

    Dim IEObject As Object
    Set IEObject = IE_Title.InternetExplorer

'---To check if the conversion worked, I inserted a MsgBox using the IsObject function below---
    
    Dim VariableCheck As Boolean
    If VariableCheck = IsObject(IEObject) Then
        MsgBox (VariableCheck)
    Else
    End If

'---As a result, the message box does appear. No errors displayed either. And the scraping evidently did not work. The only thing that works is the Internet Explorer window activation. So there must be an issue here---

    Call TestScrape2  'Calling the next Sub
End If

ErrorHandler:
    If Err.Number > 0 Then 'TODO: handle specific error
        Err.Clear
        Resume Next
    End If
End Sub

而下面的代码就是下一个Sub(TestScrape2):

Option Explicit

Sub TestScrape2()
    
    Dim IEObject As Object
    Set IEObject = New InternetExplorer

    IEObject.Visible = True
    Dim IEDocument As HTMLDocument
    Set IEDocument = IEObject.Document
        
    Debug.Print IEDocument.getElementbyId("firstHeading").innerText
        
End Sub

有什么想法吗?关于如何调用一个 Sub 中使用的变量并将其转换为另一个 Sub 中的对象变量?

希望这足够清楚

尝试Set对象:

    Dim IEObject As Object
    Set IEObject = IE_Title.InternetExplorer

另外,像这样检查:

    Dim VariableCheck As Boolean

    VariableCheck = IsObject(IEObject)
    MsgBox CStr(VariableCheck)

消息框不显示,因为 VariableCheck 为假而 IsObject(IEObject) 为真。此外,IE_Title 是一个字符串,我认为 Set IEObject = IE_Title.InternetExplorer 是错误的语法。

如果想将变量从sub1传递给sub2,可以参考

作为解决方法,您可以将 IE 变体从 sub1 传递到 sub2,然后获取 IE 的 url 并打开一个新的 Internet Explorer window url。您可以查看以下示例:

Option Explicit

Sub IEGetActivePage()

Dim marker As Variant
Dim IE_Window As Variant
Dim IE_count As Variant
Dim X As Variant
Dim IE_Title As Variant   'The web page used in this code is the following: https://fr.wikipedia.org/wiki/Visual_Basic_for_Applications
Dim IE As Variant

marker = 0
Set IE_Window = CreateObject("Shell.Application")
IE_count = IE_Window.Windows.Count

For X = 0 To (IE_count - 1)
    On Error GoTo ErrorHandler
    IE_Title = IE_Window.Windows(X).Document.Title
    If IE_Title Like "Visual Basic for Applications — Wikipédia" Then
        Set IE = IE_Window.Windows(X)
        marker = 1
        Exit For
    Else
    End If
Next

If marker = 0 Then
    MsgBox ("The Internet window cannot be found")
Else
    AppActivate IE_Title     
    TestScrape2 IE  'Calling the next Sub
End If

ErrorHandler:
    If Err.Number > 0 Then 'TODO: handle specific error
        Err.Clear
        Resume Next
    End If
End Sub

Sub TestScrape2(IE As Variant)
    
    Dim IEObject As Object
    Set IEObject = New InternetExplorer

    IEObject.Visible = True
    IEObject.navigate IE.LocationURL
    
    While IEObject.Busy
       DoEvents
    Wend
        
    Debug.Print IEObject.Document.getElementbyId("firstHeading").innerText
        
End Sub

因此,在将 @Gustav for the message box, @Toddleson for the module-level variable and @Yu Zhou 的答案结合到他的示例中后,这里是适合我的代码:

Option Explicit
Public IE_Title As Variant 'The web page used in this code is the following: https://fr.wikipedia.org/wiki/Visual_Basic_for_Applications
Sub IEGetActivePage()

Dim marker As Variant
Dim IE_Window As Variant
Dim IE_count As Variant
Dim X As Variant
Dim IE As Variant

marker = 0
Set IE_Window = CreateObject("Shell.Application")
IE_count = IE_Window.Windows.Count

For X = 0 To (IE_count - 1)
    On Error GoTo ErrorHandler
    IE_Title = IE_Window.Windows(X).Document.Title
    If IE_Title Like "Visual Basic for Applications — Wikipédia" Then
        Set IE = IE_Window.Windows(X)
        marker = 1
        Exit For
    Else
    End If
Next

If marker = 0 Then
    MsgBox ("The Internet window cannot be found")
Else
    AppActivate IE_Title     
    TestScrape2 IE  'Calling the next Sub
End If

ErrorHandler:
    If Err.Number > 0 Then 'TODO: handle specific error
        Err.Clear
        Resume Next
    End If
End Sub

Sub TestScrape2(IE_Title As Variant)
    
    Dim IEObject As Object
    Set IEObject = New InternetExplorer

    IEObject.Visible = True
    IEObject.Navigate IE_Title.LocationURL
    
    Do While IEObject.Busy = True Or IEObject.ReadyState <> READYSTATE_COMPLETE
        Application.Wait Now + TimeValue("00:00:05")
    Loop
    
    Debug.Print IEObject.LocationURL
            
End Sub

以下是我相对于之前的代码所做的更改,以及关于此问题的假设结论:

  • 在模块脚本的顶部将 IE_Title 声明为模块级变量(或作为 public 变量) ,而不是仅在第一个 Sub 上声明它(如我的初稿所示)。这允许第二个 Sub 重用变量而不会在变量类型声明中产生冲突。

  • 忘记了在同一个 Sub 中转换变量的想法。它可能在其他一些情况下有效。也许高级用户会让它工作,但我很高兴这个脚本可以正常工作哈哈。

  • 从第一个 中创建一个重复的 Internet Explorer window 以使脚本工作。 @Yu Zhou 建议的这个简单的代码行 IEObject.Navigate IE_Title.LocationURL 改变了游戏规则(尽管我保留了 IE_Title 而不是 IE,后者不起作用)。由于第一个 Sub 识别正确的 IE window,它还存储有关打开的 window 的属性信息,例如 URL,在这种情况下可以重复使用。

  • 我也意识到虽然有一个重复的 IE window 可能是多余的,但脚本按原样工作并且在最后关闭重复项并不是这样大不了。

  • 在第二个Sub中添加一个临时的MsgBox来确认IE_Object是一个对象变量。它没有显示在上面的代码中,但我将它们添加到我的版本中以检查没有什么阻止脚本。

谢谢大家!

N.B.: 嘿,你是阅读这篇文章的高级用户,如果你能简化这个脚本,请随时在这里分享:-)