3

I am new to the forum and have some VBA experience, but not a lot.

I am using Selenium to facilitate interaction with a Chrome site with the aim of automating a series of requests to the site (Starleaf Web meetings) with the data in an Excel spreadsheet.

I can log in fine and can navigate from page to page using FindElementByID and FindElementByTag("a").Click statements.

I have a problem with navigating using this approach on one page. I have tried ByID(the first 2 IDs in the code below), ByLinkText, ByClass (portalContent, button, single), ByCssSelector; but nothing works. The macro stalls on code line of this form:

Set elem = bot.FindElementBy*****("Parameter")
    elem.FindElementByTag("a").Click

The code on the page in question is:

<div class="portalContent">
    <div id="viewConferencesAddDiv" class="buttons single" style="">
        <a id="viewConferences_add" href="https://portal.starleaf.com/#page=addUserConference" target="_parent">
            <span id="viewConferences_add_text">Schedule meeting</span>
        </a>
    </div>    

I wondered if the id="viewConferences_add" between the 'a' tag and the href might be the problem but I am not sure how to get round this.

An alternative approach that I have tried to use is to go directly to the page I need after login however this does not seem to work. I may have a syntax problem???

Here's what I tried:

 bot.Get "/#page=addUserConference"
 bot.Get "https://portal.starleaf.com/#page=addUserConference"
 bot.Get "//portal.starleaf.com/#page=addUserConference"

With this code afterwards to allow time for the page to load:

 Do Until InStr(1, bot.Url, "addUserConference") > 0
 Application.Wait (DateAdd("s", 1, Now))
 DoEvents
 Loop

Update

I was looking around and found someone talking about iframe switching. Looking at the page in F12 it does actually look as thought the 'Schedule Meeting' button might be in an iframe. The suggestion was to switch to if however I have no idea how to do that. There appear to be several iframes on the page - so I guess I need the ID. I think it might be id=mainPanel_iframe.

HTML of the iframe tag:

<iframe id="mainPanel_iframe" name="mainPanel_iframe" class="mochaIframe" src="https://portal.starleaf.com/pbx/node-1.live.pr.starleaf.com/portal/#page=users&amp;lang=en_int" marginwidth="0" marginheight="0" frameborder="0" scrolling="auto" style="height: 579px; width: 1543px;"></iframe>
Pᴇʜ
  • 56,719
  • 10
  • 49
  • 73
JonR
  • 67
  • 1
  • 8
  • Are you getting error messages? If so, what? Have you checked the element isn't within a frame/iframe parent? – QHarr Mar 29 '20 at 17:14
  • @QHarr You were right. Now when in the iframe I can only do one `bot.FindElement SendKeys before an error: ```bot.Wait 5000 bot.SwitchToFrame "mainPanel_iframe" bot.Wait 5000 bot.FindElementById("editConference_label").SendKeys "Test Jonathan" bot.FindElementById("editConference_start").SendKeys "30/03/2020" bot.FindElementById("editConference_startTime").SendKeys "17:00" bot.FindElementById("editConference_end").SendKeys "30/03/2020" bot.FindElementById("editConference_endTime").SendKeys "18:00"``` – JonR Mar 29 '20 at 23:36

1 Answers1

3

To click on the link with text as Schedule meeting you need to induce some wait and you can use either of the following Locator Strategies:

  • Using FindElementByCss:

    bot.wait 5000
    bot.FindElementByCss("a#viewConferences_add[href*='addUserConference'] > span#viewConferences_add_text").Click
    
  • Using FindElementByXPath:

    bot.wait 5000
    bot.FindElementByXPath("//a[@id='viewConferences_add' and contains(@href, 'addUserConference')]/span[@id='viewConferences_add_text']").Click
    

Update

If the desired element is within an <iframe> first you need to SwitchToFrame as follows:

  • Using FindElementByCss:

    bot.wait 5000
    bot.SwitchToFrame "mainPanel_iframe"
    bot.wait 5000
    bot.FindElementByCss("a#viewConferences_add[href*='addUserConference'] > span#viewConferences_add_text").Click
    
  • Using FindElementByXPath:

    bot.wait 5000
    bot.SwitchToFrame "mainPanel_iframe"
    bot.wait 5000
    bot.FindElementByXPath("//a[@id='viewConferences_add' and contains(@href, 'addUserConference')]/span[@id='viewConferences_add_text']").Click
    

You you can find a find a relevant detailed discussion in How to send text with in the username field within an iframe using Selenium VBA


Reference

Ways to deal with #document under iframe

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • Thanks. I am still getting this error situation: Run-time error '7': NoSuchElementError Element not found for XPath=//a[@id='viewConferences_add' and contains(@href, 'addUserConference')]/span[@id='viewConferences_add_text']. Perhaps I am NOT on the page I think I am even though it is displaying? Is this a possibility? How could I tell? Could you suggest how to go directly to the page reference by a Get statement. Sorry not getting on with this editor - how do you do put in more code? J – JonR Mar 29 '20 at 13:34
  • @JonR Checkout the updated answer and let me know the status. – undetected Selenium Mar 29 '20 at 17:25
  • I tried the additional code and as dot.Wait(5000)(as the 'help' seemed to suggest brackets) but it did not work - same error point. I was looking around and found someone talking about iframe switching. Looking at the page in F12 it does actually look as thought the 'Schedule Meeting' button might be in an iframe. The suggestion was to switch to if however I have no idea how to do that. There appear to be several iframes on the page - so I guess I need the ID. I think it might be id=mainPanel_iframe. Does this help? Thanks – JonR Mar 29 '20 at 18:11
  • @JonR Checkout the updated answer and let me know the status. – undetected Selenium Mar 29 '20 at 18:20
  • Great that you know the strategy. I tried this code: bot.SwitchToFrame "mainPanel_iframe" but am not sure that this what you meant I assume your code was a template of SINGLE possibilities? The code line on the website is . Near to a solution I think. And thanks – JonR Mar 29 '20 at 20:32
  • @JonR Checkout the updated answer and let me know the status. – undetected Selenium Mar 29 '20 at 20:39
  • I tried both options however code stalls at the same point - no progression past the Schedule Meeting button within the iframe, which goes here: https://portal.starleaf.com/#page=addUserConference. I did take your lead and fashioned a statement which actually gets me to this url directly after login: bot.FindElementByXPath("//a[@class='sidebar-add-shortcut' and contains(@href, 'addUserConference')]/span[@class='iconic']").Click. This is good. However I NOW need to add data into (yes!) the same iframe id="mainPanel_iframe". Problem =iframe entry. Oh dear. – JonR Mar 29 '20 at 21:39
  • @JonR Do you realize how necessary it is to share the HTML of the iframe within the question? – undetected Selenium Mar 29 '20 at 21:43
  • ``Apologies for editor incompetence – JonR Mar 29 '20 at 22:10
  • @JonR Checkout the updated answer and let me know the status. – undetected Selenium Mar 29 '20 at 22:13
  • 1
    Yes that does it. The page https://portal.starleaf.com/#page=addUserConference loads. – JonR Mar 29 '20 at 22:29
  • 1
    Yes that does it. Thank you. The page https://portal.starleaf.com/#page=addUserConference loads. Let me try to figure out how get the data in. Best J – JonR Mar 29 '20 at 22:42
  • How do the bot.Wait 5000 work to resolve this please J – JonR Mar 29 '20 at 22:45
  • @JonR I don't practice [tag:excel-vba] that often so I would leave it up to you to dig out :) – undetected Selenium Mar 29 '20 at 22:47
  • with vba your options are 1) hard coded wait with Application.Wait Now + TimeSerial(h, m, s) 2) set up a loop for an element to be != Nothing or nodeList.Length > 0 ; Loop While element Is Nothing combined with a time out (See [here](https://stackoverflow.com/a/54231597/6241235) ; 3) Write a custom js wait function and execute/return its value in a loop via execute_script method of driver instance. – QHarr Mar 30 '20 at 06:38
  • 1
    @QHarr Thanks a lot. As usual you have rescued us again. – undetected Selenium Mar 30 '20 at 07:20