0

I'm stuck, in VBA I would like to access HTML elements on a page that uses AngularJS,

All those elements "exist", because I see them when I use the IE debugger tool. They are all in a parent div with class called "cont".

Problem :

when I look the source code of the site, this div is empty. I can see only the structure, which is :

 <div 
        class="cont"
        data-ng-controller=".."
        ..
        data-ng-init="initApplication()">
</div>

but nothing inside.. it's loaded probably after by angular.

So when I try to access a button inside this div, example with :

Set IE = CreateObject("InternetExplorer.Application")
IE.document.getElementsById("submitBtn").click

then I get an error saying that the object doesn't exist..

So I tried to add that before :

' wait until IE and the page are ready
Do While .Busy Or Not .readyState = 4: DoEvents: Loop
' wait until the DOM is ready
Do Until .document.readyState = "complete": DoEvents: Loop

but nothing works, I don't understand at all, is it possible to access HTML elements inside this div? why I see evthg in the debugger tool?

Any idea ??


UPDATE

I found that the content of the div is located in a .js file, there are millions of things there but there is :

angular.module("cont").factory("applicationService",["$rootScope","ngDialog","webService",
function(a,b,c){
    "use strict";
     var d={},
     e="home";
     d.initApplication=function(){
          return c.initContact()
     }

and also :

angular.module("cont").run(["$templateCache",function(a){"use     strict";
a.put("Application",'ALL THE CONTENT IS HERE (with an HTLM element I would like to click)!!!!!'
Julien
  • 3,743
  • 9
  • 38
  • 67
  • Possible duplicate of [Use getElementById on HTMLElement instead of HTMLDocument](http://stackoverflow.com/questions/15191847/use-getelementbyid-on-htmlelement-instead-of-htmldocument) – Asons Jun 03 '16 at 18:23
  • You need to show more of your existing code - those two lines don't tell us much. If the element shows up in the Ceveloper Tools source then you should be able to access it. Note also that `getElementsById` should be `getElementById` (without the "s") – Tim Williams Jun 03 '16 at 18:33
  • Is your button in a frame? Do you get a result with `document.getElementsById("submitBtn")` in the console of your browser? – Florent B. Jun 03 '16 at 19:40
  • no not in a frame, and I get null in the console – Julien Jun 03 '16 at 19:42
  • @Julient And with `document.getElementById("submitBtn")` without an "s" or `document.querySelector("#submitBtn")` ? – Florent B. Jun 03 '16 at 19:50
  • yes this "s" it was a typo written here, but the same.. but I may found sthg, I updated the question with what I found – Julien Jun 03 '16 at 19:54
  • Having the HTML, even partially would help. You'll never get the expected result in VBA if you can't find the target element with the console. – Florent B. Jun 03 '16 at 20:05

1 Answers1

0

The elements do not exist in the source code because they have not been created by javascript yet. You see them with F12 because when you use the debugger tool on the page, the javascript has run and created the elements.

Consider this javascript snippet:

var btn = document.createElement("BUTTON");

The page will not have a button until the javascript has run. After the code has run, the element exists and you will be able to interact with it. I suspect hat your code attempting to get submitBtn is running before the javascript which creates that button runs.

Without seeing the script that creates the button, my best suggestion would be to Do While .Busy Or Not .readyState = 4: DoEvents: Loop like you already do, but then start testing for the existence of the button like this (admittedly inelegant approach):

'Declare Sleep at the top of you code module
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds as Long)

Sub mySub()
    Dim objButton as Object
    'Code creating nd automating IE here
    Do While .Busy Or Not .readyState = 4: DoEvents: Loop
    'May possibly need On Error Resume Next here
:TryAgain
    Set objButton = IE.document.getElementsById("submitBtn")
    If objButton Is Nothing Then 
        Sleep 1000 'Wait for 1 second
        GoTo TryAgain
    End If
    'On Error GoTo 0 if you needed resume next
    'At this point objButton is something, so let's try clicking it
    objButton.Click
End Sub

Unfortunately there isn't an event that gets fired when javascript gets run, so we pretty much have to wait for it to finish.

If the javascript won't run unless you do something (eg, click, move the mouse, press a key, etc), you may be able to use .execScript to force the script to run regalrdless. See this SO post for more information: How to call javascript function in VBA

Community
  • 1
  • 1
Tim
  • 2,701
  • 3
  • 26
  • 47
  • thanks again Tim, yes you're right, it's probably not yet created by javascript, so I tried to put a sleep but I get an "object require" error just after the Tryagain, the line where the button is set.. – Julien Jun 03 '16 at 19:25
  • Yeah, sorry, I didn't test the code. I wasn't sure if attempting to set an object with a non-existent element would result in an Object Required error or an empty object. Add (or edit and uncomment) the `On Error` lines, and it *should* continue. It still might not work though since I'm not sure what causes the javascript to run and create the button (hopefully its the OnLoad event!) :D – Tim Jun 03 '16 at 19:29
  • yes it doesn't work, I also tried with a sleep of 10seconds, the same, grr – Julien Jun 03 '16 at 19:33
  • Just to verify, the instance of IE you are creating is visible, correct? IE and JS are notable for not doing things or firing events when the window is hidden or minimized. You may want to investigate the script that is creating the button and force it to run using `execScript`. Automating IE with dynamically created elements is a pain. :P Another potential way to skin this cat is to [create your own POST](http://stackoverflow.com/questions/158633/how-can-i-send-an-http-post-request-to-a-server-from-excel-using-vba) Then you don't have to fiddle around clicking a non-existent button. – Tim Jun 03 '16 at 19:42
  • I think I found sthg interesting, indeed you're right, the div content is loaded by angular, I found it in a js file, I updated the question with what I found there.. indeed all this div content! – Julien Jun 03 '16 at 19:58