miércoles, 15 de octubre de 2014

VBA: Rellenando un formulario web HTML desde Excel.

Aprenderemos hoy a rellenar un formulario o similar en HTML dentro de una web, empleando Internet Explorer (como complementario que es de Office) utilizando un simple código de VBA para Excel.
Para facilitar la comprensión, realizaremos una búsqueda en Google, ejecutando una macro desde nuestro Excel.


Veamos en primer lugar el código insertado en un módulo de nuestro Libro de trabajo:

Sub RellenarWEBGoogle()
'www.excelforo.com
Dim IE As Object
'creamos el objeto para el navegador Internet Explorer
Set IE = CreateObject("InternetExplorer.application")
'dentro del navegador, accedemos al buscador Google (o cualquier otra wev con un formulario tipo HTML
IE.Navigate "https://www.google.es/"

Do
    DoEvents
Loop Until IE.readystate = 4

'para completar el campo de búsqueda:
'código identificado en la url www.google.es:
'input id=gbqfq class=gbqfif name=q type=text autocomplete=off value=""
IE.Document.getelementbyid("gbqfq").Value = "excelforo"
'para realizar la búsqueda presionamos el botón de Buscar..
''código identificado en la url www.google.es:
'button class="gbqfba" aria-label="Buscar con Google" id="gbqfba" name="btnK"
IE.Document.getelementbyid("gbqfba").Click
'IE.Document.All("btnK").Click otra forma de llamarlo..

'finalmente hacemos visible la ventana de Internet Explorer
IE.Visible = True

End Sub



Fundamental para el correcto funcionamiento es instalar la referencia Microsoft Internet Controls, desde el menú Herramientas > Referencias del editor de VBA:

VBA: Rellenando un formulario web HTML desde Excel.



Si lanzamos y ejecutamos nuestra macro, conseguiremos ver directamente:

VBA: Rellenando un formulario web HTML desde Excel.



Para comprender correctamente el código empleado, debemos saber localizar el Id o Name de los cuadros de texto o botones que vayamos a completar o presionar (clicar), siempre en un lenguaje HTML.. ya que otros formularios en script no son accesibles...

El primer paso, en la barra de direcciones del navegador (para este paso se recomienda o FireFox o Google Chrome), introduciremos la url indicada (en nuestro ejemplo: www.google.es).
En segundo lugar, con el botón derecho del ratón, seleccionaremos Inspeccionar Elemento sobre el 'cuadro de búsqueda':

VBA: Rellenando un formulario web HTML desde Excel.


Seguidamente se nos desplegarán, en la parte inferior del navegador unas ventanas con código HTML que refleja lo que vemos... remarcado en azul la parte de código que afecta al elemento clicado:


Y para el botón 'Buscar con google...' la misma acción, sobre él, presionamos botón derecho e Inspeccionar elemento:



fijémosnos en el código HTML de uno y otro elemento:
1-Para el cuadro de búsqueda...
input id="gbqfq" class="gbqfif" name="q" type="text" autocomplete="off" value="" aria-haspopup="false" role="combobox" aria-autocomplete="both" dir="ltr" spellcheck="false" style="border: none; padding: 0px; margin: 0px; height: auto; width: 100%; position: absolute; z-index: 6; left: 0px; outline: none; background: url(data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw%3D%3D) transparent;"

2- Para el botón de buscar...
button class="gbqfba" aria-label="Buscar con Google" id="gbqfba" name="btnK"

Es fundamental, para emplearlo en nuestro código VBA para Excel, localizar de cada elemento, la característica Id (o Name):
Para el cuadro de búsqueda: id="gbqfq" y name="q";
Para el botón: id="gbqfba" y name="btnK"


Por desgracia existen multitud de formularios en las diferentes web que no emplean HTML, o no tienen definidos estos parámetros Id o Name... pero merece la pena intentarlo.

Por supuesto los valores a incorporar, lo podemos extraer de nuestras celdas, por ejemplo en la línea:
IE.Document.getelementbyid("gbqfq").Value = "excelforo"

por

IE.Document.getelementbyid("gbqfq").Value = Range("A1").Value

34 comentarios:

  1. Hola buenas. Ya tengo funcional el codigo de cargar pagina, rellenar el formulario y clickear en buscar, ahora estoy intentado asignar parte del texto del resultado a una variable de vba. Intento hacer whois desde excel, y que de cada ip te de el pais.

    Como puedo asignar el texto de la pagina a una variable?

    (estoy practicando con esta pagina de whois y con ips de prueba)
    http://whois.urih.com/record/80.5.4.8/

    Y lo suyo seria obtener el pais del campo 4 o 22.

    Saludos y gracias por la pagina.

    ResponderEliminar
    Respuestas
    1. Hola,
      no he probado nunca.. pero en teoría, si ya tienes identificado el id, definir una variable con el dato sería tan sencillo como:
      NombreVariable=IE.Document.getelementbyid("gbqfq").Value

      o el Id que tengas...

      Espero te funcione.
      Saludos

      Eliminar
  2. Buenas y gracias de antemano por la info facilitada, me ha servido de ayuda.
    Pero me surge una duda.
    Yo accedo a mi formulario inicial (www.mipagina.com/default.aspx) relleno los input y presiono el botón, como indicas. Esto funciona perfectamente y me carga la página siguiente (también en www.mipagina.com/default.aspx) con nuevos input y button. Cuando quiero hacer click del botón de la segunda página, no encuentra el elemento.
    Alguna sugerencia para "refrescar" los elementos del IE.Document con los de la segunda página?
    Un saludo.

    ResponderEliminar
    Respuestas
    1. Hola,
      en teoría el bucle
      Do
      DoEvents
      Loop Until IE.readystate = 4

      sirve para parar y continuar (refrescar) lo que vemos.
      Prueba colocando un nuevo bucle después de la primera página

      Espero te pueda ayudar.
      Slds

      Eliminar
  3. hola!!! muchas gracias por publicar este tema, creo que es muy potente su aplicación, lamentablemente no he logrado hacer que abra el Internet Explorer, sabes si debe modificarse alguna configuración para que la macro lo pueda abrir?

    gracias!!!

    ResponderEliminar
    Respuestas
    1. Hola Luis,
      te has asegurado de instalar la referencia que se comenta en el post??
      'Fundamental para el correcto funcionamiento es instalar la referencia Microsoft Internet Controls, desde el menú Herramientas > Referencias del editor de VBA'

      Saludos

      Eliminar
  4. Hola amigo saludos. Gracias desde ya por tu ayuda.
    Yo necesito Refrescar una Lista desplegable cuyos valores dependen de otra lista. Es decir, que el control internamente cargue los valores o indices.

    ResponderEliminar
  5. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  6. En 1er lugar agradecerle por su respuesta muy rápida, en 2do lugar disculparme por no detallar bien mi problema.
    Mi pregunta es con respecto a Rellenar un Formulario Web aspx desde Excel VBA.
    He logrado poner los valores en 3 ComboBox, pero hay un 4to Combo q depende de lo q elija en este 3er Combo, he usado el código de tu Blog y es lo siguiente, pero nada queda en blanco:
    Abrir_IE.document.getElementById("ctl00_ContentPlaceMain_ddlSeccion").Click
    Abrir_IE.document.getElementById("ctl00_ContentPlaceMain_ddlSeccion").Value = Range("e12")

    El código fuente HTML queda así:
    <-- Seleccionar -->

    Luego del click q yo hago manualmente queda así:
    <-- Seleccionar -->
    A
    B
    C
    D
    E

    Necesito simular un click en ese objeto para q cargue o refresque los valores en el objeto para recién asignarle el Value.
    Ahora si detalle bien mi problema. Gracias por compartir sus conocimientos, estaré pendiente de su respuesta.

    ResponderEliminar
    Respuestas
    1. Hola Jimmy,
      en principio no conozco otra forma que con esa propiedad .click

      podría ser más un tema del formulario Web que un problema del código... por desgracia no siempre es posible atacar formularios webs desde Excel, ya que los webmaster tienen herramientas para evitar entradas desde robots u otros accesos automatizados.

      Siento no poder darte una respuesta clara.
      Un cordial saludo y suerte
      P.D.: si lo logras, por favor, compártelo aquí!

      Eliminar
  7. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  8. Me gustaria compartir el codigo, tal vez en algo estoy fallando, y alguien pueda compartir la solución:

    Sub RellenarNotas()
    Dim Abrir_IE As Object

    Set Abrir_IE = CreateObject("internetexplorer.Application")
    With Abrir_IE
    .Top = 1
    .Left = 1
    .Width = 600
    .Height = 400
    .Visible = True
    .navigate ("http://sistemas10.minedu.gob.pe/siagie3/ExamenPorSeccion.aspx?sPms=Up11f8wTMi7VbctOh4deCw%3d%3d")
    Do While Abrir_IE.busy
    DoEvents
    Loop
    Application.Wait (Now + TimeValue("0:00:03"))
    End With

    Abrir_IE.document.getElementById("ctl00_ContentPlaceMain_ddlPeriodo").Value = Range("d8")
    Abrir_IE.document.getElementById("ctl00_ContentPlaceMain_ddlGrado").Value = Range("e11")

    Do While Abrir_IE.busy
    DoEvents
    Loop

    Abrir_IE.document.getElementById("ctl00_ContentPlaceMain_ddlGrado").Click

    Application.Wait (Now + TimeValue("0:00:03"))
    Abrir_IE.document.getElementById("ctl00_ContentPlaceMain_ddlSeccion").Value = "01"

    'Tambien esta linea de codigo me deja en blanco la lista desplegable:
    'Abrir_IE.document.getElementById("ctl00_ContentPlaceMain_ddlSeccion").javascript = "javascript:setTimeout('__doPostBack(\'ctl00$ContentPlaceMain$ddlSeccion\',\'\')', 0)"
    End Sub

    Ahora mi pregunta seria si es que es posible ejecutar codido javascrip desde VBA Excel, tal vez ahi está la solución. GRACIAS

    ResponderEliminar
    Respuestas
    1. Hola,
      si es posible... aunque nunca lo he usado leí algo al respecto hace bastante tiempo, se trata del método de windows execscript,
      por ejemplo:
      IE.Document.parentWindow.execScript "ctl00_ContentPlaceMain_ddlSeccion;"
      no controlo mucho de java... pero quizá te de la pista.
      Slds

      Eliminar
  9. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  10. Hola Ismael, aqui otra vez 1ro para compartir la solución y 2do para hacerte una nueva consulta:
    1. SOLUCIÓN usando el Método windows execscript:
    Sub RellenarNotas()
    Dim Abrir_IE As Object
    Set Abrir_IE = CreateObject("internetexplorer.Application")
    With Abrir_IE
    .Top = 1
    .Left = 1
    .Width = 600
    .Height = 400
    .Visible = True
    .Navigate ("http://sistemas10.minedu.gob.pe/siagie3/ExamenPorSeccion.aspx?sPms=Up11f8wTMi7VbctOh4deCw%3d%3d")
    Do While Abrir_IE.Busy: DoEvents: Loop
    Application.Wait (Now + TimeValue("0:00:03"))
    End With

    Abrir_IE.Document.getElementById("ctl00_ContentPlaceMain_ddlPeriodo").Value = Range("d8")
    Abrir_IE.Document.getElementById("ctl00_ContentPlaceMain_ddlGrado").Value = Range("e11")

    Abrir_IE.Document.parentWindow.execScript "javascript: setTimeout('__doPostBack(\'ctl00$ContentPlaceMain$ddlSeccion\',\'\')', 0)", "JavaScript"
    Application.Wait (Now + TimeValue("0:00:01"))
    Abrir_IE.Document.getElementById("ctl00_ContentPlaceMain_ddlSeccion").Value = Range("e12")

    Abrir_IE.Document.parentWindow.execScript "javascript:setTimeout('__doPostBack(\'ctl00$ContentPlaceMain$ddlArea\',\'\')', 0)", "JavaScript"
    Application.Wait (Now + TimeValue("0:00:01"))
    Abrir_IE.Document.getElementById("ctl00_ContentPlaceMain_ddlArea").Value = Range("i8")

    ' A partir de aquí mi pregunta
    Abrir_IE.Document.getElementById("ctl00_ContentPlaceMain_btnRegistroResumen").disabled = False
    Abrir_IE.Document.getElementsByName("ctl00$ContentPlaceMain$btnRegistroResumen").Item.Click

    End Sub

    2. Cuando hago Click en el "Boton REGISTRO" se abre otra ventana de IE y es en donde pondre las notas de estudiantes, y al cual ya no puedo controlar; ¿Cómo haría para tener control de esa nueva ventana, o tal vez Cómo a partir de ese click crear un nuevo objeto IE y de ahi si podria controlar todos sus elementos?
    -He intentado creando otro objeto IE a partir del Link que genera el Boton REGISTRO, pero se abren 2 ventanas iguales.
    Tal vez necesite crear una Funcion o almacenar ese objeto o ese Click en una Variable, estas 2 cosas lo desconozco.
    Desde ya GRACIAS por tu ayuda.

    ResponderEliminar
  11. AYUDA POR FAVOR...
    Cuando hago Click en el "Boton REGISTRO" se abre otra ventana de IE y es en donde pondre las notas de estudiantes, y al cual ya no puedo controlar; ¿Cómo haría para tener control de esa nueva ventana, o tal vez Cómo a partir de ese click crear un nuevo objeto IE y de ahi si podria controlar todos sus elementos?
    -He intentado creando otro objeto IE a partir del Link que genera el Boton REGISTRO, pero se abren 2 ventanas iguales.
    Tal vez necesite crear una Funcion o almacenar ese objeto o ese Click en una Variable, estas 2 cosas lo desconozco.
    Desde ya GRACIAS por tu ayuda.

    ResponderEliminar
    Respuestas
    1. Hola,
      lo siento... no sabría darte una respuesta.
      Slds

      Eliminar
    2. A ver si te valiera ésto:

      En el código:
      Dim ie2 as internetExplorer

      ...

      Set ie2 = Nothing

      (instrucciones para que ie1 abra la ventana emergente)

      Set ie2 = GetIE("url de la ventana nueva")

      Función GetIE

      Function GetIE(sLocation As String) As Object
      'Devuelve el InternetExplorer que tiene por url sLocation

      Dim objShell As Object, o As Object
      Dim sURL As String
      Dim RetVal As Object

      Set RetVal = Nothing
      Set objShell = CreateObject("Shell.Application")

      For Each o In objShell.Windows
      sURL = ""
      On Error Resume Next
      sURL = o.locationURL
      On Error GoTo 0
      'Debug.Print sURL
      If sURL Like sLocation & "*" Then
      Set RetVal = o
      Exit For
      End If
      Next o

      Set GetIE = RetVal

      End Function

      Eliminar
  12. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  13. hola buenas tardes, me parece muy interesante y admirable lo que haces al ayudarnos y darnos excelentes inicio s para experimentos, sabes? tengo una duda que me detiene en un proyectito y espero que puedas ayudarme, en tu basta experiencia crees que pueda importar datos de una pagina web que ya esta cargada en un navegador externo a excel? digase firefox o chrome o ie? es que ya intente hacerlo de forma directa pero no puedo al momento de hacerlo por codigo me es casi imposible ya que debo de introducir varios datos de los cuales obtengo varios resultados y de alli debo elegir el que busco y entonces la pagina arroja una tabla, la cual es la que necesito cargar a excel una vez que he cargado las variables anteriores, crees que eso sea posible???? muchas gracias

    ResponderEliminar
    Respuestas
    1. Hola Erick,
      en principio si es posible, ya que cada vez que navegamos en una Web interaccionamos y son acciones que se pueden representar y replicar desde las macros de Excel...
      Ahora bien, la realidad es que todo es más complejo que la teoría, y no siempre es posible replicar los movimientos que plasmamos :(
      El asunto se complica aún un poco más si en lugar de IE lo queremos hacer sobre Chrome, FireFox, etc...

      Un saludo y suerte!!

      Eliminar
  14. Hola a todos, necesito algo similar a esto pero que funcione en el navegador TOR, sera posible?

    ResponderEliminar
    Respuestas
    1. Hola,
      no conozco ese navegador.. pero supongo existirá su librería y podrás instalarla en Excel para poder trabajar con él...
      ??
      Slds

      Eliminar
  15. hola,
    tengo una duda, he intentado hacer exactamente lo que comentais pero me encuentro que el boton de entrar no tiene ni nombre ni id, podriais decirme cual seria la instrucción?

    pego el codigo del boton:

    input type="submit" value="Entrar">

    codigo vba:


    Sub RellenarWEBGoogle()

    Dim IE As Object

    Set IE = CreateObject("InternetExplorer.application")

    IE.Navigate "https://www.sumasa.net/SOL/"

    Do
    DoEvents

    Loop Until IE.readystate = 4


    IE.Document.all("j_username").Value = "1111"
    IE.Document.all(j_password").value = "1212"

    IE.Document.getelementbytype("submit").Click


    IE.Visible = True

    End Sub

    ResponderEliminar
    Respuestas
    1. Hola Marc,
      lo normal en url de control de acceso, cuando están bien diseñados, es que eviten accesos de robots, o desde otras aplicaciones.. como es el caso, por lo que se vuelve muy complicado poder rellenarlos desde fuera...

      Saludos

      Eliminar
  16. Hola Ismael, excelente artículo, muchas gracias por compartirlo y por ayudarnos :)

    Estoy tratando de completar un formulario pero no puedo acceder a el desde VBA.

    Te comento, para acceder al formulario debo pasar el mouse sobre el menú y darle clic a uno de los sub-sub-menús, el menú principal si tiene ID pero los sub-menus no.

    Te comparto parte del código de la página para ver si me puedes ayudar en algo.

    De nuevo, gracias por el aporte.

    Saludos :D

    ResponderEliminar
    Respuestas
    1. table style="top: 0px;" border="0" cellspacing="0" cellpadding="0"
      tbody
      tr id="ctl00_ucMenuTools_mainMenun30" onmouseover="Menu_HoverDynamic(this)" onmouseout="Menu_Unhover(this)" onkeyup="Menu_Key(event)"
      td
      table width="100%" class="navigate ctl00_ucMenuTools_mainMenu_6" border="0" cellspacing="0" cellpadding="0"
      tbody
      tr
      td style="width: 100%; white-space: nowrap;"
      a class="ctl00_ucMenuTools_mainMenu_1 navigate ctl00_ucMenuTools_mainMenu_5"
      style="font-size: 1em;" href="../Audit/Procedure/,DanaInfo=.abndpwDtwHwo35ysOs54,SSL+listProcedure.aspx?Type=E">Resultados de Auditoría
      /a
      /td
      /tr
      /tbody
      /table
      /td
      /tr
      /tbody
      /table

      Eliminar
    2. Hola,
      lo normal es localizar el campo por Id o por Name...
      a veces es inaccesible (leer otros comentarios arriba).

      O también es posible estén dentro de otra parte del código, empleando otros scripts.. o incluso otros lenguajes (java, por ejemplo)...

      Lo siento pero no puedo ayudarte; un saludo y suerte!

      Eliminar
  17. no puedo hacer que la macro pegue usuario y contraseña en una pagina de dhl ya tengo el id y nombre, lo he intentado de varias formas y no funciona
    pagina.getElementsByName("j_username").innerText = usuario
    pagina.getElementById("j_password").innerText = contrasena
    ya intente poniendo Document en lugar de pagina

    ResponderEliminar
    Respuestas
    1. Hola Cristina,
      la propiedad debería ser mejor .Value (en lugar de .InnerText)
      En todo caso, lee los comentarios anteriores... verás que se indica que en ciertas páginas, por protección de sus webmaster, se impide el acceso exterior.

      Saludos

      Eliminar
  18. Buen dia

    alguien sabe como darle click a un boton de tipo "input type="button" value="Siguiente" onclick="goToReceptor()" class="btn"

    goToReceptor este se encuentra en un JS que dice

    function goToReceptor() {
    $("#__next").val("GeneracionCfdi/1");
    $("#__valida").val("false");
    changeActionForm("/Cfdi/NextGeneracionCfdi");
    }
    Gracias

    ResponderEliminar