使用VBA在网页上按下按钮,而不用打开IE [英] Press a button on a webpage using VBA and without opening IE

查看:318
本文介绍了使用VBA在网页上按下按钮,而不用打开IE的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道是否可以在网页上单击按钮,而无需在IE中打开页面。网页是动态生成的,点击按钮会调用脚本来改变页面的内容。



我可以通过这个子菜单打开Internet Explorer:

  Sub DownloadPageScript(strUrl As String,htmlPage as htmlDocument,strScript As String)

Dim IE As对象

设置IE = CreateObject(InternetExplorer.application)
IE.navigate strUrl


DoEvents
Loop Until IE。 ReadyState = READYSTATE_COMPLETE

'运行与按钮关联的脚本以获取数据
IE.Document.parentWindow.execScript strScript,jscript


DoEvents
循环直到IE.ReadyState = READYSTATE_COMPLETE

设置htmlPage = IE.Document

结束Sub

但是我想避免打开Internet Explorer,所以我想这样:

  Sub Download_Page(strU RL作为字符串,htmlPage作为HTMLDocument的,strScript作为字符串)

尺寸XMLHTTP作为对象
'
将XMLHTTP =的CreateObject( MSXML2.XMLHTTP)
XMLHTTP。打开GET,strUrl,False
xmlHttp.setRequestHeaderContent-Type,text / xml
xmlHttp.send
'
'这里我应该添加一些内容来执行脚本
'
'执行后
'
设置htmlPage =新htmlDocument
htmlPage.body.innerHTML = xmlHttp.ResponseText
'
End Sub

我期望能找到类似于 xmlHttp.execute(args )方法来复制单击按钮的操作,但我错了。
所以我的问题是:如果我不想打开Internet Explorer,是否可以复制按钮点击?如果是的话我该怎么办?


基于评论中的想法的新方法



我尝试了@omegastripes在评论中建议的方法,并且我写下了他的答案



对于页面上的实际表:





希望这会有所帮助。


I was wondering if it is possible to "click a button" on a webpage without opening the page in IE. The webpage is dynamically generated and the click on the button calls a script that changes the content of the page.

I am able to do this opening Internet Explorer with this sub:

Sub DownloadPageScript(strUrl As String, htmlPage As htmlDocument, strScript As String)

  Dim IE            As Object

  Set IE = CreateObject("InternetExplorer.application")
  IE.navigate strUrl

  Do
      DoEvents
  Loop Until IE.ReadyState = READYSTATE_COMPLETE 

  ' Run the scripts associated to the button to get the data
  IE.Document.parentWindow.execScript strScript, "jscript"

  Do
      DoEvents
  Loop Until IE.ReadyState = READYSTATE_COMPLETE

  Set htmlPage = IE.Document

End Sub

But I would like to avoid opening Internet Explorer so I would like to something like this:

Sub Download_Page(strUrl As String, htmlPage As htmlDocument, strScript As String)

  Dim xmlHttp      As Object
  '
  Set xmlHttp = CreateObject("MSXML2.XMLHTTP")
  xmlHttp.Open "GET", strUrl, False
  xmlHttp.setRequestHeader "Content-Type", "text/xml"
  xmlHttp.send
  '
  ' Here I should add something to execute the script
  ' 
  ' After execution
  '
  Set htmlPage = New htmlDocument
  htmlPage.body.innerHTML = xmlHttp.ResponseText
  '
End Sub

I was expecting to find something like a xmlHttp.execute(args) method to replicate the action of clicking the button but I was wrong. So my question is: Is it possible to replicate the button click if I do not want to open Internet Explorer? and if yes what should I do?

New approach based on the idea in the comments

I tried the approach suggested by @omegastripes in the comments and I wrote this sub taken by his answer 33484763:

Sub TestDownload()

  Dim xmlHttp      As Object
  Dim htmlPage       As htmlDocument
  Dim strExportURL   As String
  Dim strFormData    As Variant
  Dim strContent     As String


    ' build exportURL parameter
  strExportURL = Join(Array( _
      "p_p_id=ScommesseAntepostPalinsesto_WAR_scommesseportle", _
      "p_p_lifecycle=2", _
      "p_p_resource_id=dettagliManifestazione", _
      "p_p_cacheability=cacheLevelPage", _
      "_ScommesseAntepostPalinsesto_WAR_scommesseportlet_codDisc=1", _
      "_ScommesseAntepostPalinsesto_WAR_scommesseportlet_codMan=21", _
      "_ScommesseAntepostPalinsesto_WAR_scommesseportlet_codScomm=3", _
      "_ScommesseAntepostPalinsesto_WAR_scommesseportlet_codClusterScomm=80", _
      "_ScommesseAntepostPalinsesto_WAR_scommesseportlet_filtro=0" _
      ), "&")

  ' build the whole form data
  strFormData = Join(Array( _
        "languageCode=en", _
        "exportURL=" & URLEncode(strExportURL) _
    ), "&")

  ' POST XHR to retrieve the content
  Set xmlHttp = CreateObject("Microsoft.XMLHTTP")
  xmlHttp.Open "POST", "http://www.sisal.it/scommesse-matchpoint/palinsesto", False
  xmlHttp.setRequestHeader "Content-Type", "application/json"
  xmlHttp.send strFormData

  Set htmlPage = New htmlDocument
  htmlPage.body.innerHTML = xmlHttp.responseText
  '
End Sub

Public Function URLEncode( _
   StringVal As String, _
   Optional SpaceAsPlus As Boolean = False _
) As String
  Dim bytes() As Byte, b As Byte, i As Integer, space As String

  If SpaceAsPlus Then space = "+" Else space = "%20"

  If Len(StringVal) > 0 Then
    With New ADODB.Stream
      .Mode = adModeReadWrite
      .Type = adTypeText
      .Charset = "UTF-8"
      .Open
      .WriteText StringVal
      .Position = 0
      .Type = adTypeBinary
      .Position = 3 ' skip BOM
      bytes = .Read
    End With

    ReDim result(UBound(bytes)) As String

    For i = UBound(bytes) To 0 Step -1
      b = bytes(i)
      Select Case b
        Case 97 To 122, 65 To 90, 48 To 57, 45, 46, 95, 126
          result(i) = Chr(b)
        Case 32
          result(i) = space
        Case 0 To 15
          result(i) = "%0" & Hex(b)
        Case Else
          result(i) = "%" & Hex(b)
      End Select
    Next i

    URLEncode = Join(result, "")
  End If
End Function

The URLEncode() function is from this post URLEncode. (I tried to use JScriptControl but It does not work probably because I have Office 64-bit).

This code runs without errors but when I look to the content of htmlPage it is almost empty. I think the problem is that the request I am sending is wrong but I am not able to correct it, can you help me?

解决方案

Consider the below example:

Option Explicit

Sub TestDownload()

    Dim strParams As String
    Dim strURL As String
    Dim strJsonString As String
    Dim varJson As Variant
    Dim strState As String
    Dim arrScommessaList() As Variant
    Dim varScommessa As Variant

    strParams = Join(Array( _
        "p_p_id=ScommesseAntepostPalinsesto_WAR_scommesseportlet", _
        "p_p_lifecycle=2", _
        "p_p_state=normal", _
        "p_p_resource_id=dettagliManifestazione", _
        "p_p_cacheability=cacheLevelPage", _
        "_ScommesseAntepostPalinsesto_WAR_scommesseportlet_codDisc=1", _
        "_ScommesseAntepostPalinsesto_WAR_scommesseportlet_codMan=21", _
        "_ScommesseAntepostPalinsesto_WAR_scommesseportlet_codClusterScomm=", _
        "_ScommesseAntepostPalinsesto_WAR_scommesseportlet_filtro=0" _
    ), "&")
    strURL = "http://www.sisal.it/scommesse-matchpoint/palinsesto?" & strParams

    With CreateObject("Microsoft.XMLHTTP")
        .Open "GET", strURL, False
        .Send
        strJsonString = .ResponseText
    End With

    ParseJson strJsonString, varJson, strState

    arrScommessaList = varJson("scommessaList")
    For Each varScommessa In arrScommessaList
        Debug.Print varScommessa("descrizioneAvvenimento")
        Debug.Print vbTab & _
        varScommessa("esitoList")(0)("formattedQuota") & vbTab & _
        varScommessa("esitoList")(1)("formattedQuota") & vbTab & _
        varScommessa("esitoList")(2)("formattedQuota")
    Next

End Sub

Sub ParseJson(ByVal strContent As String, varJson As Variant, strState As String)
    ' strContent - source JSON string
    ' varJson - created object or array to be returned as result
    ' strState - Object|Array|Error depending on processing to be returned as state
    Dim objTokens As Object
    Dim lngTokenId As Long
    Dim objRegEx As Object
    Dim bMatched As Boolean

    Set objTokens = CreateObject("Scripting.Dictionary")
    lngTokenId = 0
    Set objRegEx = CreateObject("VBScript.RegExp")
    With objRegEx
        ' specification http://www.json.org/
        .Global = True
        .MultiLine = True
        .IgnoreCase = True
        .Pattern = """(?:\\""|[^""])*""(?=\s*(?:,|\:|\]|\}))"
        Tokenize objTokens, objRegEx, strContent, lngTokenId, bMatched, "str"
        .Pattern = "(?:[+-])?(?:\d+\.\d*|\.\d+|\d+)e(?:[+-])?\d+(?=\s*(?:,|\]|\}))"
        Tokenize objTokens, objRegEx, strContent, lngTokenId, bMatched, "num"
        .Pattern = "(?:[+-])?(?:\d+\.\d*|\.\d+|\d+)(?=\s*(?:,|\]|\}))"
        Tokenize objTokens, objRegEx, strContent, lngTokenId, bMatched, "num"
        .Pattern = "\b(?:true|false|null)(?=\s*(?:,|\]|\}))"
        Tokenize objTokens, objRegEx, strContent, lngTokenId, bMatched, "cst"
        .Pattern = "\b[A-Za-z_]\w*(?=\s*\:)" ' unspecified name without quotes
        Tokenize objTokens, objRegEx, strContent, lngTokenId, bMatched, "nam"
        .Pattern = "\s"
        strContent = .Replace(strContent, "")
        .MultiLine = False
        Do
            bMatched = False
            .Pattern = "<\d+(?:str|nam)>\:<\d+(?:str|num|obj|arr|cst)>"
            Tokenize objTokens, objRegEx, strContent, lngTokenId, bMatched, "prp"
            .Pattern = "\{(?:<\d+prp>(?:,<\d+prp>)*)?\}"
            Tokenize objTokens, objRegEx, strContent, lngTokenId, bMatched, "obj"
            .Pattern = "\[(?:<\d+(?:str|num|obj|arr|cst)>(?:,<\d+(?:str|num|obj|arr|cst)>)*)?\]"
            Tokenize objTokens, objRegEx, strContent, lngTokenId, bMatched, "arr"
        Loop While bMatched
        .Pattern = "^<\d+(?:obj|arr)>$" ' unspecified top level array
        If Not (.test(strContent) And objTokens.Exists(strContent)) Then
            varJson = Null
            strState = "Error"
        Else
            Retrieve objTokens, objRegEx, strContent, varJson
            strState = IIf(IsObject(varJson), "Object", "Array")
        End If
    End With
End Sub

Sub Tokenize(objTokens, objRegEx, strContent, lngTokenId, bMatched, strType)
    Dim strKey As String
    Dim strRes As String
    Dim lngCopyIndex As Long
    Dim objMatch As Object

    strRes = ""
    lngCopyIndex = 1
    With objRegEx
        For Each objMatch In .Execute(strContent)
            strKey = "<" & lngTokenId & strType & ">"
            bMatched = True
            With objMatch
                objTokens(strKey) = .Value
                strRes = strRes & Mid(strContent, lngCopyIndex, .FirstIndex - lngCopyIndex + 1) & strKey
                lngCopyIndex = .FirstIndex + .Length + 1
            End With
            lngTokenId = lngTokenId + 1
        Next
        strContent = strRes & Mid(strContent, lngCopyIndex, Len(strContent) - lngCopyIndex + 1)
    End With
End Sub

Sub Retrieve(objTokens, objRegEx, strTokenKey, varTransfer)
    Dim strContent As String
    Dim strType As String
    Dim objMatches As Object
    Dim objMatch As Object
    Dim strName As String
    Dim varValue As Variant
    Dim objArrayElts As Object

    strType = Left(Right(strTokenKey, 4), 3)
    strContent = objTokens(strTokenKey)
    With objRegEx
        .Global = True
        Select Case strType
            Case "obj"
                .Pattern = "<\d+\w{3}>"
                Set objMatches = .Execute(strContent)
                Set varTransfer = CreateObject("Scripting.Dictionary")
                For Each objMatch In objMatches
                    Retrieve objTokens, objRegEx, objMatch.Value, varTransfer
                Next
            Case "prp"
                .Pattern = "<\d+\w{3}>"
                Set objMatches = .Execute(strContent)

                Retrieve objTokens, objRegEx, objMatches(0).Value, strName
                Retrieve objTokens, objRegEx, objMatches(1).Value, varValue
                If IsObject(varValue) Then
                    Set varTransfer(strName) = varValue
                Else
                    varTransfer(strName) = varValue
                End If
            Case "arr"
                .Pattern = "<\d+\w{3}>"
                Set objMatches = .Execute(strContent)
                Set objArrayElts = CreateObject("Scripting.Dictionary")
                For Each objMatch In objMatches
                    Retrieve objTokens, objRegEx, objMatch.Value, varValue
                    If IsObject(varValue) Then
                        Set objArrayElts(objArrayElts.Count) = varValue
                    Else
                        objArrayElts(objArrayElts.Count) = varValue
                    End If
                    varTransfer = objArrayElts.Items
                Next
            Case "nam"
                varTransfer = strContent
            Case "str"
                varTransfer = Mid(strContent, 2, Len(strContent) - 2)
                varTransfer = Replace(varTransfer, "\""", """")
                varTransfer = Replace(varTransfer, "\\", "\")
                varTransfer = Replace(varTransfer, "\/", "/")
                varTransfer = Replace(varTransfer, "\b", Chr(8))
                varTransfer = Replace(varTransfer, "\f", Chr(12))
                varTransfer = Replace(varTransfer, "\n", vbLf)
                varTransfer = Replace(varTransfer, "\r", vbCr)
                varTransfer = Replace(varTransfer, "\t", vbTab)
                .Global = False
                .Pattern = "\\u[0-9a-fA-F]{4}"
                Do While .test(varTransfer)
                    varTransfer = .Replace(varTransfer, ChrW(("&H" & Right(.Execute(varTransfer)(0).Value, 4)) * 1))
                Loop
            Case "num"
                varTransfer = Evaluate(strContent)
            Case "cst"
                Select Case LCase(strContent)
                    Case "true"
                        varTransfer = True
                    Case "false"
                        varTransfer = False
                    Case "null"
                        varTransfer = Null
                End Select
        End Select
    End With
End Sub

The output is:

For actual table on the page:

Hope this helps.

这篇关于使用VBA在网页上按下按钮,而不用打开IE的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆