我想使用VBA从网页上获取表格,但我无法直接访问它,因为我需要从标签页切换到另一个标签页。问题依赖于网页的.aspx端(URL不会相应地发展)。
网址:http://www.morningstar.fr/fr/fundquickrank/default.aspx
Default page after clicking URL
Moving to "Long Terme" Tab - URL won't change
我设法构建了将表格导出到Excel工作表的代码,但缺少“导航”部分。
以下是关于点击“Long Terme Tab”按钮的HTML代码:
我的出发点在这里(ProcessHTMLPage执行表格抓取):
Sub Browse_Morningstar()
Dim XMLPage As New MSXML2.XMLHTTP60
Dim HTMLDoc As New MSHTML.HTMLDocument
XMLPage.Open "GET", "http://www.morningstar.fr/fr/fundquickrank/default.aspx", False
XMLPage.send
HTMLDoc.body.innerHTML = XMLPage.responseText
ProcessHTMLPage HTMLDoc
End Sub
我想这个请求必须以某种方式更新。 对不起,如果我不够准确,但我对这一切都很陌生。
非常感谢你们!
答案 0 :(得分:1)
当您检查与选择主内容div栏相关联的HTML时,例如Long Terme
,您可以看到有一个与单个条形项目的onclick
事件相关联的java脚本__doPostBack
function。
观察相关HTML:
引用我上面的链接:
该函数采用以下两个参数:
eventTarget - 包含导致该控件的控件的ID 回帖。 eventArgument - 包含任何其他数据 与控制相关联。
在任何ASP.NET页面中有两个隐藏字段:__ EVENTTARGET和 自动声明__EVENTARGUMENT。当页面回发到服务器时,ASP.NET会检查__EVENTTARGET和__EVENTARGUMENT 值和这样它可以决定哪个控件导致了 要回发的页面以及必须处理的事件。
在" olden" ASP
天通常必须有一个表单来捕获用户输入,然后创建其他页面以接受这些输入(GET
或POST
),验证,执行操作等。使用ASP.NET
,您可以在接受上述参数的服务器上声明控件,并在检查
第一个参数告诉您触发了哪个控件,第二个参数提供了其他信息,在这种情况下,它确定返回哪些选项卡信息。
我们可以从上面看到TabAction
是控件,其后面的数字对应于感兴趣的标签,例如2为Long Terme(为0 - 索引)。
在VBA中,我们可以通过多种方式执行此JS函数,但我将使用:
.document.parentWindow.execScript "__doPostBack('EVENTTARGET', 'EVENTARGUMENT')"
这变为:
.document.parentWindow.execScript "__doPostBack('TabAction', '2')"
我重新编写以接受EVENTARGUMENT作为常量OPTION_CHOSEN
,因此可以通过更改顶部的值来检索不同的标签。
执行该函数后,剩下一点时间来刷新页面,然后该表被id
抓取:
Set hTable = .document.getElementById("ctl00_ctl00_MainContent_Layout_1MainContent_gridResult")
然后表格沿着行和列循环(列是沿着每行长度的表格单元格)。
来自页面的示例:
代码输出中的示例:
完整代码:
Option Explicit
Public Sub GetTable()
Dim IE As New InternetExplorer
Const OPTION_CHOSEN As Long = 2 '0 Aperçu; 1 Court terme; 2 Long terme; 3 Portefeuille; 4 Frais & Détails
Application.ScreenUpdating = True
With IE
.Visible = True
.navigate "http://www.morningstar.fr/fr/fundquickrank/default.aspx"
While .readyState < 4: DoEvents: Wend
.document.parentWindow.execScript "__doPostBack('TabAction', ' " & OPTION_CHOSEN & "')"
Do While .Busy = True Or .readyState <> 4: DoEvents: Loop
Dim hTable As HTMLTable, tRow As HTMLTableRow, tCell As HTMLTableCell
Set hTable = .document.getElementById("ctl00_ctl00_MainContent_Layout_1MainContent_gridResult")
Dim c As Long, r As Long
With ActiveSheet
For Each tRow In hTable.Rows
For Each tCell In tRow.Cells
c = c + 1: .Cells(r + 1, c) = tCell.innerText
Next tCell
c = 0: r = r + 1
Next tRow
.Columns("A:A").Delete
.UsedRange.Columns.AutoFit
End With
.Quit
End With
Application.ScreenUpdating = True
End Sub
参考文献(VBE&gt;工具&gt;参考文献):
答案 1 :(得分:0)
Sub Get_Info()
Dim Elems, e As Variant
Const READYSTATE_COMPLETE& = 4&
Dim ie As Object
Set ie = Nothing
DoEvents
Set ie = CreateObject("InternetExplorer.Application")
DoEvents
With ie
.Visible = True
.Navigate "http://www.morningstar.fr/fr/fundquickrank/default.aspx"
While Not .readyState = READYSTATE_COMPLETE
DoEvents
Wend
End With
With ie.Document
Set Elems = .getElementsByTagName("span")
DoEvents
For Each e In Elems
If e.getAttribute("onclick") = "__doPostBack('TabAction', '2')" Then
e.Click
'try to insert your table export code here
Exit For
End If
Next e
End With
Set Elems = Nothing
Set e = Nothing
'ie.Quit Quit Internet Explorer once the exporting is done
Set ie = Nothing
MsgBox "Done"
End Sub
上面的代码直接导航到您想要的标签。尝试将它与您的代码结合起来导出表格,也许它会起作用。 ie.Visible = True只是为了确保你导航到正确的URL,但是一旦你看到它工作就把它弄错。希望它有所帮助!
答案 2 :(得分:0)
如果您希望使用IE从该目标页面获取表格数据,那么这就是实现这一目标的一种方法。
Sub Fetch_Data()
Dim IE As New InternetExplorer, html As HTMLDocument
Dim posts As Object, post As Object, elem As Object, trow As Object
With IE
.Visible = True
.navigate "http://www.morningstar.fr/fr/fundquickrank/default.aspx"
While .readyState < 4: DoEvents: Wend
Set html = .document
End With
For Each post In html.getElementsByClassName("ms_tab_inactivetext")
If InStr(post.innerText, "Long terme") > 0 Then post.ParentNode.Click: Exit For
Next post
Do While IE.Busy = True Or IE.readyState <> 4: DoEvents: Loop
Set posts = html.getElementById("ctl00_ctl00_MainContent_Layout_1MainContent_gridResult")
For Each elem In posts.Rows
For Each trow In elem.Cells
c = c + 1: Cells(r + 1, c) = trow.innerText
Next trow
c = 0: r = r + 1
Next elem
IE.Quit
End Sub
参考添加到库:
1. Microsoft HTML Object Library
2. Microsoft Internet Controls