I am trying to send an email over Microsoft 365 using IE as the browser. I am currently having difficulty getting VBA to create a new email and am trying to do so by simply telling it to click the "New Mail" button which has the following HTML code:
<button autoid="_n_j" type="button" class="_n_j2 o365button" aria-labelledby="_ariaId_31" regionbehavior="1">
<span class="_n_l2 owaimg ms-Icon--plus ms-bcl-tp ms-bg-transparent ms-icon-font-circle ms-fcl-tp ms-icon-font-size-20-circle" role="presentation"></span>
<span class="_n_k2 ms-font-weight-regular ms-font-color-themePrimary" id="_ariaId_31">New mail</span>
</button>
I am trying to press this using the following VBA code:
Dim objButton As Object
Set objButton = IE.Document.getElementById("_n_j2 o365button")
objButton.onfocus
objButton.onclick
But am getting a run time error. I think this is because the button is using javascript (page doesnt reload when pressed, just updates). Any ideas how to do this?
Try IE.Document.GetElementsByClassName("_n_j2 o365button")(0).Click
You can't use .GetElementByID() because the button hasn't been assigned an ID.
I've used .GetElementsByClassName() because we know that the button has a class assigned, however a class is not unique. This method returns a collection of all elements with this class - without seeing the whole HTML, I'm going to make an assumption that all buttons on the page share this class.
The (0) tells the code to click the first item stored in the collection.
(Again, I'm going to assume you don't have something like Option Base 1 declared)
You might have to iterate through the collection and somehow test each item to see which button you need and change the (0) accordingly.
Related
I'm creating a Django website where I want to implement such functionality.
There will be one Dropdown list and one submit button. When user selects any item from dropdown list - An image according to user selection will be displayed.
ie. There's drop-down list containing names of animals and one submit button. When user selects any animal from list, photo/details of that animal should appear before pressing submit button.
I don't know how to create link between them. Any reference to such work or advice would be appreciate.
Thank you :)
You likely want to use async request with JavaScript here (look for AJAX or JS Fetch API)
Attach it to onchange event of select element and send it's value to django.
Django will have a view that processes this request and returns a JsonResponse with image url.
Alternatively you can load all urls before hand and just select them on page without request, but anyway if you don't want to press button to take change - you need JavaScript.
I am currently creating an automation to fill-in field in the browser (Chrome) with VBA and selenium. Which is currently doing fine. (the site is internal)
However, I came across with this "message from web" prompt after saving / submitting the information. Sometimes, this pop-up box gives me a prompt that it was saved successfully and sometimes, if there are errors, the message box contains some text.
In order for me to handle this pop-up message box and put some validation. In this case, I would like to get the text inside this message box. (Please refer to the red arrow).
The code below is what I used in order to accept / click the "OK" button. And doesn't have any problems. However, as mentioned, I would like to get the text inside that box to put some validation.
What I tried so far:
driver.SwitchToAlert
driver.SwitchToAlert.Text <<<--- this is where I attempt to get the text however, it doesn't work.
driver.SwitchToAlert(20).accept
Also, I have check below code:
driver.switchTo().alert().getText();
However, this seems not to be working in VBA / selenium.
Try such a code (Change to suit your issue)
Dim bot As Selenium.ChromeDriver
Sub Test()
Dim dlg As Selenium.Alert
Set bot = New Selenium.ChromeDriver
With bot
.Get "http://the-internet.herokuapp.com/javascript_alerts"
.FindElementByCss("#content > div > ul > li:nth-child(2) > button").Click
Set dlg = .SwitchToAlert(Raise:=False)
Debug.Print dlg.Text
.Wait 2000
dlg.Dismiss
End With
End Sub
I've been poking around the internet at large cobbling together some VBA code to try to interact with some web pages (and eventually scrape).
I have some decent knowledge of VB and programming, but the internet end of things is pretty new to me, especially the syntax of commands, so I'm leveraging things from the internet.
I have one that's working,
http://snowload.atcouncil.org/
This I can fill in and get to submit with a
doc.getelementsbyId("coordinate_address").value = range("City").value _
& ", " & range("State").value
doc.getelementsbyId("btn-submit").click
then wait it out until readystate =4 , etc.
The one I can't get to work is here.
http://windspeed.atcouncil.org/
This one seems to use a object that I can't figure out how to click. It doesn't seem to have a name, and Id, etc.
If I use conventional 'submit' on the windspeed page, (loosely using that term), the page loads, but it comes out blank. Like I'm not using the syntax correctly, or not passing a variable/searchform somehow.
ie.document.all.item("submit").click
This 'works' but it produces a blank page with the east coast of africa and no data.
In the immediate/console of the browser, after I click, say, the Hawaii button, it works with document.searchform.submit()
If I try that in code, it doesn't work. (The Immediate window in the VBA editor thows me a "expected: =" error,
The object I am trying to click is in the web site code.....
<span>
<input type="submit" value="Get Windspeed" onclick="valbutton(searchform); return false;">
<span>
I've tried a lot of techniques poached from the internet, but no success yet. (looping over elements using getelementsbyclassname "span", but it either doesn't find the one with value ="Get Windspeed", or it doesn't find it at all.
somehow triggering the valbutton (that's a subroutine/function on the page) seems like a workaround... but VBA seems to want different syntax than the console on the web page and it's doing the same kind of "expected: =" syntax error when I try that approach.
I suspect normal submit would work, but I'm somehow not passing the filled out page and am sending a blank to the submit/get?
I also notice that if you are on the page, type in an address, and hit enter, it runs that "find" button I can't figure out (same thing, no name or ID obvious, it's a button....), and if you hit enter after it reloads, then it somehow by default hits that 'get windspeed' button, which suggests to me they are both submit buttons in a way.
Thanks for reading, I appreciate any thoughts on the matter. I am trying to get this to get all the data input and get the results without adding anything beyond VBA (i.e. jscript or vbscript or other things,)
-Brian
You should be able to simply submit the form after setting the .Value of the inputs.
doc.getelementsbyId("searchform").submit
I was able to adapt this (despite the claim this doesn't work in IE11..., maybe I'm not using 11...Is eleven Miscrosoft Edge?)
https://www.mrexcel.com/forum/excel-questions/344297-need-visual-basic-applications-code-execute-javascript.html
IE.Document.parentWindow.execScript "CheckAndSubmit(document.frmViewMyAcct);"
that allowed me to mimic hitting the button or hitting submit and somehow got around the 'no information / resulting page is blank' issue. The onclick event has a javascript routine attached to it, so I just copied that syntax.
Thanks for the help, it got me started on the solution.
Regards,
Brian
I know this is a common problem, and I tried a few solutions already, but the problem I have right now with my current code is that even though the attachments show in the computed for display field, I get the error "Note Item not Found" when I try to open them.
The form is built with two fields, in a programmable table that displays the editable one or the computed for display one.
The trick I found with Google's help was to delete the computed for display item in the queryopen event, so Notes regenerates the cfd item when opening the document. Visually, this works, as I see the text and attachments, but the attachments can't be opened.
Here is the code that removes the item in the QueryOpen of the form:
...
Set item = doc.GetFirstItem("dspDescription")
If Not item Is Nothing Then Call item.Remove()
...
Has anyone successfully achieved that functionality? Is there another way of doing this? I already tried with subforms, and because of the way the application is built, I need to be able to switch from editable to read only on the flick of a radio button, so subforms are out of the question as they can't be displayed dynamically.
Why don't you simple put the richtext item in a controlled access section and make that section editable / not editable with a computed for display formula. Select "always expand" and hide the section title, so that nobody can collapse it, et voila.
Regarding your comment: With this properties:
for this section in designer:
You get this result:
You see: No twisty, no "visible" section
I am struggling with the following.
On my XPage I have a viewpanel component, but it is not bound to a notesview datasource, but to a hashmap stored in viewScope. Reasons for this is beyond scope of my question.
Since the lines in my view are not actually linked to the documents I cannot use the standard checkboxes and the related getSelectedDocIds. I do however want a way to remove the selected documents. I have a column with checkboxes containing the unid of the corresponding row.
So long story short. I have an array of unids and want to perform an action that does the following:
Display a dijit.Dialog asking for confirmation
If OK clicked call a function that does the following:
Remove the documents based on the unids
Refresh the viewpanel
I am thinking of the following 2 solutions, but in doubt what would be best (maybe a third, even simpler solution?)
Have the OK button of the dojo dialog call a function that does an XmlHttpRequest to an XAgent or plain old LS agent
Have the OK button trigger an eventhandler that runs on the server as described by JeremyHodge here. But how would I pass the unids as parameter and refresh the view afterwards?
Thanks!
Cant you just make use of the extension library dialog with the dialog button control. In this button control you can then
A third option would be to add a column to your datatable/view which contains checkboxes. On the onchange event of these boxes you add an eventhander which adds the value to a viewScope variable.
A button on the bottom (or top.) of the page you add the code you need to remove the selected items from the hashmap, delete the documents associate with the selected id's. this button can be a ordinary button with a partial refresh on the viewpanel. When you run into the bug that you cant use buttons in a dialog please use the extension library dialog control because this fixes that issue for you.
If the current user does not have the correct access level to delete documents you could use the sessionAsSigner global (assuming the signer of the design element has the correct access levels).
This way you dont need to go call an xAgent by xmlthttprequest and can stay with the default xpage methodology.
I hope this helps in some way
I would second #jjbsomhorst in the use of the extension library for the dialog box - if you use one at all. Usually users don't read dialog boxes. So the approach would be add the column with the checkboxes, but don't bother with an event handler, but bind them ALL with their value to ONE scopeVariable. On submission that variable will then hold an array with the selected UNID.
Then render a page that lists these documents and have a confirm button. While the new page affords a server round-trip the likelihood, that users actually pay attention is way higher. What you can do:
Have the normal page that renders the dialog with editable checkboxes and when the user clicks "Delete" you set something like viewScope.confirmDeleteMode=true; and use that as condition for the checkboxes and make them read-only AND set the class of the selected rows to "morituri" which in your CSS would have something like .morituri { color: white; background-color : red; font-weight: bold } and a new button "Confirm Delete" (and hide the Delete button).
This way you only have one page to deal with.
I went for option 2, which has the possibility to provide the partial refresh id. I passed the unids as a submitvalue like:
function doRemove(unids){
XSP.executeOnServer(ISP.UI.removeEventID, ISP.UI.removeRefreshID, {
params: {
'$$xspsubmitvalue': unids
},
onComplete : function() {
//alert('test')
}
});
}
The ISP.UI.removeEventID performs the following code:
var unids = context.getSubmittedValue();
removeDocuments(unids); //SSJS function performing the actual delete
viewScope.reload = 'reload' //triggers the hashmap to be rebuild based on new documentcollection