我正在开发 VBA 代码以帮助保持 Excel 工作簿与https://www.fel.mx/CFDI33/Presentacion/Usuario/Ingreso.aspx上的 Web 发票服务同步
我使用 Internet Explorer 对象开发了一些工作功能,并决定试试运气,将其迁移到 XMLHTTP 以希望获得更好的性能和可靠性。我现在正在处理的功能只是登录到 Web 服务并获取所有已取消发票的列表
到目前为止,我已经能够越过登录屏幕,导航到发票注册表,按“已取消”状态过滤发票列表并导航到结果的第二页。我遇到的问题(听起来很傻)是进入第三页及以后(我知道事实上还有更多页面,我什至可以使用“最后一页”按钮进入最后一页,但是不要到第 3 页到“最后 - 1”)。
对于上下文,这段代码将使我通过登录屏幕:
'Define xmlhttp request and html response objects
Dim xmlhttp_request As Object
Dim html_response As HTMLDocument
Set xmlhttp_request = CreateObject("Msxml2.XMLHTTP")
Set html_response = CreateObject("htmlFile")
'Get FEL login website html. We need this to later URL encode our POST data including the _EVENT params and our login credentials
With xmlhttp_request: .Open "GET", FEL_WEBSITE_LOGIN, False: .send: End With
'Put the xmlhttp responsetext in our html object
html_response.body.innerHTML = xmlhttp_request.responseText
'URL encode our password
encoded_password = WorksheetFunction.EncodeURL(FEL_PASSWORD)
'Prepare our POST data string
'We include the encoded _EVENT params, our login credentials and the login button item
post_data = _
"__VIEWSTATE=" & WorksheetFunction.EncodeURL(html_response.getElementById("__VIEWSTATE").Value) & _
"&__EVENTVALIDATION=" & WorksheetFunction.EncodeURL(html_response.getElementById("__EVENTVALIDATION").Value) & _
"&txtUsuario=" & FEL_USERNAME & _
"&txtCuenta=" & FEL_USERNAME & _
"&txtContrena=" & encoded_password & _
"&btnInicioSesion=Iniciar sesión"
'POST our xmlhttp request including our post data
With xmlhttp_request
.Open "POST", FEL_WEBSITE_LOGIN, False
.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
.setRequestHeader "Content-Length", Len(post_data)
.send (post_data)
End With
然后,这将使我在 2017 年的每个月以“已取消”状态进入结果过滤发票的第一页:
With xmlhttp_request: .Open "GET", FEL_WEBSITE_CFDI_REGISTRY, False: .send: End With
html_response.body.innerHTML = xmlhttp_request.responseText
post_data = _
"__VIEWSTATEENCRYPTED=" & _
"&__VIEWSTATE=" & WorksheetFunction.EncodeURL(html_response.getElementById("__VIEWSTATE").Value) & _
"&__EVENTVALIDATION=" & WorksheetFunction.EncodeURL(html_response.getElementById("__EVENTVALIDATION").Value) & _
"&ctl00$ContentPlaceHolder1$ddlMes=Todos" & _
"&ctl00$ContentPlaceHolder1$ddlAno=2017" & _
"&ctl00$ContentPlaceHolder1$ddlEstadoComprobante=1"
With xmlhttp_request
.Open "POST", FEL_WEBSITE_CFDI_REGISTRY, False
.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
.setRequestHeader "Content-Length", Len(post_data)
.send post_data
End With
然后,之后我可以这样做以进入第二页:
(事实上,我认为我在这里所做的是再次过滤结果然后转到下一页,而不是仅仅从先前过滤的结果中转到下一页。我认为这是问题的一部分;请继续阅读以获取更多信息细节)
html_response.body.innerHTML = xmlhttp_request.responseText
post_data = _
"ctl00$ContentPlaceHolder1$ddlDia=Todos" & _
"&ctl00$ContentPlaceHolder1$ddlMes=Todos" & _
"&ctl00$ContentPlaceHolder1$ddlAno=2017" & _
"&__VIEWSTATE=" & WorksheetFunction.EncodeURL(html_response.getElementById("__VIEWSTATE").Value) & _
"&__PREVIOUSPAGE=" & WorksheetFunction.EncodeURL(html_response.getElementById("__PREVIOUSPAGE").Value) & _
"&__EVENTVALIDATION=" & WorksheetFunction.EncodeURL(html_response.getElementById("__EVENTVALIDATION").Value) & _
"&__VIEWSTATEENCRYPTED=" & _
"&ctl00$ContentPlaceHolder1$pagCFDI$btnSiguiente="
With xmlhttp_request
.Open "POST", FEL_WEBSITE_CFDI_REGISTRY, False
.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
.setRequestHeader "Content-Length", Len(post_data)
.send post_data
End With
这就是我所得到的。在那之后,我终生无法翻到第三页。我以为我可以重新发送相同的 POST 请求,但这只是再次返回第 2 页。
正如您可以想象的那样,我刚刚开始涉足 XMLHTTP,所以这对我来说还是有点陌生。
我觉得我需要的是:
- 发送相同的 POST 请求,但发送到前一个 POST 请求的响应 URL,而不是再次发送到 FEL_WEBSITE_CFDI_REGISTRY(XMLHTTP 对象中似乎没有 responseURL 属性),或者
- 也许我需要处理某种 cookie 来帮助 XMLHTTP 对象跟踪当前页面。
谁能看到我错过了什么?