如何将 VARIANT 变量从一个子程序传递并转换为另一个子程序中的 OBJECT 变量?
How to pass & convert a VARIANT variable from one sub to an OBJECT variable in another sub?
我正在努力处理我的 VBA 代码。我有两个潜艇:
- 第一个 Sub 识别并弹出我的抓取宏将在其上运行的 Internet Explorer window。这个 Sub (IEGetActivePage) 工作正常;
- 第二个 Sub 将执行抓取工作。此 Sub 需要使用 Internet Explorer 弹出的对象变量 window.
我的目标是从第一个 Sub (IEGetActivePage) 调用 VARIANT 变量 IE_Title 到下一个 Sub ( TestScrape2) 并将其转换为 OBJECT 变量(以便 TestScrape2 中的代码正常工作)。
编辑:
SET
功能似乎不起作用。我得到相同的结果:弹出 Internet Explorer window,但仅此而已。甚至没有 MsgBox 来检查变量类型。
这是 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.: 嘿,你是阅读这篇文章的高级用户,如果你能简化这个脚本,请随时在这里分享:-)
我正在努力处理我的 VBA 代码。我有两个潜艇:
- 第一个 Sub 识别并弹出我的抓取宏将在其上运行的 Internet Explorer window。这个 Sub (IEGetActivePage) 工作正常;
- 第二个 Sub 将执行抓取工作。此 Sub 需要使用 Internet Explorer 弹出的对象变量 window.
我的目标是从第一个 Sub (IEGetActivePage) 调用 VARIANT 变量 IE_Title 到下一个 Sub ( TestScrape2) 并将其转换为 OBJECT 变量(以便 TestScrape2 中的代码正常工作)。
编辑:
SET
功能似乎不起作用。我得到相同的结果:弹出 Internet Explorer window,但仅此而已。甚至没有 MsgBox 来检查变量类型。
这是 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.: 嘿,你是阅读这篇文章的高级用户,如果你能简化这个脚本,请随时在这里分享:-)