简体   繁体   中英

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

I'm struggling with my VBA code. I have two Subs:

  • The first Sub identifies & pops up the Internet Explorer window on which my scraping macro will work on. This Sub ( IEGetActivePage ) works fine;
  • The second Sub will do the scraping job. This Sub requires the use of the object variable which poped up the Internet Explorer window.

My goal is to call the VARIANT variable IE_Title from the first Sub ( IEGetActivePage ) into the next Sub ( TestScrape2 ) and convert it to an OBJECT variable (for the code in TestScrape2 to work).


EDIT:

  • The SET function does not seem to work. I get the same result: the Internet Explorer window pops up but nothing more. Not even the MsgBox to check the variable type.

This is the IEGetActivePage code, with the IE_Title variable:

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

And the following code is the next 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

Any ideas? On how to call a variable used in a Sub and converting it to an object variable in another Sub?

Hopefully this is clear enough

Try to Set the object:

    Dim IEObject As Object
    Set IEObject = IE_Title.InternetExplorer

Also, check like this:

    Dim VariableCheck As Boolean

    VariableCheck = IsObject(IEObject)
    MsgBox CStr(VariableCheck)

The message box doesn't show because VariableCheck is false and IsObject(IEObject) is true. Besides, IE_Title is a string, I think Set IEObject = IE_Title.InternetExplorer is wrong syntax.

If you want to pass a variable from sub1 to sub2, you can refer to this answer .

As a workaround, you can pass the IE variant from sub1 to sub2, then get the url of IE and open a new Internet Explorer window with the url. You can check the sample below:

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

So after combining the answers of @Gustav for the message box, @Toddleson for the module-level variable and @Yu Zhou for his sample, here's the code that works for me:

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

Below are the changes I have made compared to the previous code, as well as hypothetical conclusions regarding this issue:

  • Declaring IE_Title as a module-level variable (or as a public variable) at the top of the module script, instead of declaring it only on the first Sub (as shown in my first draft). This allows the second Sub to reuse the variable without creating a conflict in the variable types declaration.

  • Forgetting the idea of converting a variable within the same Sub . It might work in some other cases. Maybe an advanced user would make it work but I'm happy with this script working as it is haha.

  • Create a duplicate Internet Explorer window out of the first one to make the script work. This simple code line IEObject.Navigate IE_Title.LocationURL suggested by @Yu Zhou was a game-changer (although I kept IE_Title instead of IE which didn't work). As the first Sub identifies the correct IE window, it also stores properties information about the opened window such as the URL, which in this case can be reused.

  • I also realized that although having a duplicate IE window can be redundant, the script works as it is and closing the duplicates at the end is not such a big deal.

  • Adding a temporary MsgBox in the second Sub to confirm that IE_Object is an object variable . It is not shown in the code above, but I added them on my version to check that nothing blocks the script.

Thanks to you all!

NB: hey you advanced user reading this, if you can simplify this script, feel free to share it here:-)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM