Pass value to textbox in website using Excel VBA - html

I am trying to navigate a website and perform activities based on input from Excel.
I am stuck in passing values to input element which auto populates value in next text box based on value we have passed (eg: if I pass a zip code in target box then city name is auto populated in next box). I can pass values but it is not triggering the JS which auto populates value.
Target box code in webpage
<input name="zipcode" class="inputBoxRequired" id="zipcode" onkeypress="return isNumberKey(event)" onblur="getZipCity(this.value,'/ProviderPortal')" type="text" size="46" maxlength="5">
Code tried
Set Zip = ie_Doc.getElementById("zipcode")
Zip.Value = Zip_Code 'Here value gets updated but associated js is not triggered
ie_Doc.getElementById("zipcode").Focus
even tried fire event
Zip.FireEvent ("onchange")
In webpage it is mentioned as Onkeypress event. I googled to find solution but I can't get exact one.

Zip.FireEvent ("onkeypress")
Zip.FireEvent ("onblur") '<== Apparently this did the trick
Those are the shown events.

I have come across the same scenario for solution verified this post whereas in my case I do not have "onblur" tag, so I did some search and come up with an solution.
Dim event_onChange As Object
Set event_onChange = ie_Doc.createEvent("HTMLEvents")
event_onChange.initEvent "keypress", True, False
Zip.dispatchEvent event_onChange
It will help others who are facing same problem.

Related

Paste a value in a textbox on the second tab of a navigation form access vba

I'm quite new to VBA and I've been looking around but cannot seem to find a solution to my problem.
I have made a navigation form (frmNavigation) with 3 buttons, each referring to a different form, let's call them frm1, frm2 and frm3. In the navigationform the control buttons to switch between tabs are all named differently (btn1, btn2, btn3), but the subform that shows either frm1, frm2, or frm3 has the same name: “NavigationSubform” (this shows a different form depending on which tab is clicked on, based on the 'navagation target name' referring to frm1, frm2 and frm3).
When I want to refer to a textbox (txtBox1) on form 1 (first tab) and insert a value i can do this by:
Forms!frmNavigation!NavigationSubform.Form!txtBox1.Value = "insert awesome text"
But how would I refer to txtbox10 on the second tab (frm2)? Just using the following does not work:
Forms!frmNavigation!NavigationSubform.Form!txtBox10.Value
You then get the error 2465 (can't find the field).
I’ve been trying many different things, but can’t seem to get it right. So how do I refer to a textbox on a different tab than the first one?
Help us much appreciated!
Only one subform can be loaded at once. So you've just got to break this process into two steps.
Store the value from txtBox1 somewhere outside of the NavigationSubforms (a textbox on the parent form with visible = no, a global variable or a table works).
In frm2's On Load event, set txtbox10 to be the value you stored.
Just note, that you will need to add conditions in the On Load event if you want to avoid that textbox being set to an empty string or a wrong value if you have a setup where your filter is changing.

Driving a website using VBA and Selenium

I have to log into SnapSurveys and download 20+ files monthly. Already a tedious process, I now have to do it weekly instead and it will be beyond tedious to do it by hand, so I want to automate it and have installed Selenium to do so. I've tracked the entire process using the SeleniumIDE (in FireFox), so I know what I want to do, and the basics of how to do it, however, I've run into an absolute brick wall trying to understand the web page structure to make it happen.
Using the Dev tools in both Chrome & FireFox, I've identified the "User Name" field as this:
<p>
<label for="UserName">Username</label>
<input data-val="true" data-val-required="The Username field is required." id="UserName" name="UserName" type="text" value="">
<span class="field-validation-valid" data-valmsg-for="UserName" data-valmsg-replace="true"></span>
</p>
I'm using the following code to attempt to locate the "Username" text box so I can type data into it. I've tried each of the values of Text, in turn, with each of the Driver.FindElementBy... possibilities, and they all give me this error:
Run-time Error '7':
NoSuchElementError
Element not found for <By type> = <text>
This is the code:
Private Sub Login()
Const SITE_BASE_NAME As String = "https://www.snapsurveys.com/login"
Dim Driver As IEDriver
Set Driver = New IEDriver
Dim IsSiteLoaded As Boolean
IsSiteLoaded = Driver.Get(SITE_BASE_NAME)
If IsSiteLoaded Then
Dim Text As String
Text = "columns six"
Text = "UserName"
Text = "main"
Text = "//*[#id=""UserName""]"
Dim El As WebElement
Set El = Driver.FindElementByClass(Text)
Set El = Driver.FindElementByCss(Text)
Set El = Driver.FindElementById(Text)
Set El = Driver.FindElementByLinkText(Text)
Set El = Driver.FindElementByName(Text)
Set El = Driver.FindElementByPartialLinkText(Text)
Set El = Driver.FindElementByTag(Text)
Set El = Driver.FindElementByXPath(Text)
End If
Driver.Quit
End Sub
The one combination I've found that's not given me an error is:
Text = "main"
Set El = Driver.FindElementById(Text)
But that only gives me the breadcrumbs at the top of the screen, and I'm not really sure how to get anywhere useful from there.
Obviously, I don't understand enough about web design to have any clue what I'm supposed to be looking for, but I thought I could trial and error my way through it with a little less frustration than this.
What element(s) do I need to be looking for in the page source, and which FindElementBy function do I need to use to search for it in code?
Further, is filling in the UserName & Password fields, clicking "Log In", then clicking on the appropriate links on the next page, etc. the best way to go about this? I think that once I've logged myself in, I should be able to get a collection of links for each file I need and directly download each link, but I'm not 100% certain if I can do that or not.
Some notes:
Yes, I realize that the code is using IE as the browser. The drivers I have for FF & Chrome seem to be out of date (browser opens, but it won't load the web page) and I haven't gotten newer ones. At the moment, I don't care what browser I use so long as I get it working.
Yes, I realize that I'm closing the browser down at the end of the Sub. Again, I'm just testing, trying to find my way in the dark.
The login functionality is inside an iframe. You have to switch selenium's focus to that iframe and then try again and it should work.
You can try this:
Driver.switchtoframe (0)
Driver.FindElementById("UserName")
Some knowledge about web design can help a long way when dealing with selenium to automate, but with just some basic knowledge you can get the work done easily.
What element you should be looking for depends on what you are trying to achieve. If you want to enter something in a text field, you should be looking for <input type="text"> elements, for table's you need to be looking for <table> elements.
I usually prefer using find elements by xpath, but if the element has a unique id or class on the webpage, you can use find element by class name or find element by id.
You seem to be going on the right track to automate your task.

Populate textboxes with value from listbox selection on child form

I realise this question has been asked before and I have tried numerous suggestions, but I guess I am just too much of a novice when it comes to VBA coding.
Here is my scenario:
I have an Access 2007 "Application" with a few forms. On the main form, I have 2 text boxes. For simplicity let's call them textbox1 and textbox2.
textbox1 is used to enter a style code. a button on the main form then opens another in modal/dialog mode and runs a query with the style code as the where clasue. the modal popup gives me a list box which is populated from the database based on the query that was passed. I then need to select one of the products in the list and upon closing the popup, populate textbox2 with the brand (column2 in the list from the popup) number.
Please remember that I am a novice. Any help would be greatly appreciated.
I would put a button on the second form, and in the _Click() function, put something like this
If ListBox1.ListIndex = -1 Then
MsgBox "Nothing Selected!"
Exit Sub
End If
UserForm1.TextBox1.Text = ListBox1.List(ListBox1.ListIndex)
Unload Me
Where ListBox1 is the list box containing the content you need the user to select from, where UserForm1 is the name of the calling form, and TextBox1 is the name.
Explanation
The ListIndex property of the list box returns the index of the selected list item. If nothing is selected, it returns a -1.
To reference an item on one from from another, you reference the form, the object and the property.
In The example I gave, the form is UserForm1, the object is TextBox1 and the Property is Text. While typing, intellisense should auto complete the object and properties once you type the period.

Use VBA to navigate a website and modify drop down box

Good Morning,
I am working a VBA project where I would like to access an internal company, login required, web site and extract data from a table. I have successfully written code that will navigate to the correct website, and then modify a drop down box value from "All Transactions" to "Running Record". The problem I have is that I cannot not get the data in the table to refresh once the drop down box is updated. On the website, next to the drop down field, is a "Go" hyperlink. Whenever I try to activate the link, using vba, it resets the drop down and I don't get the data displayed that I want.
I was able to find a similar post where a user explained that the issue was related to the site being secured and that a .FireEvent would need to be used. Although the concept made sense to me implementation was another story. The biggest difference between my situation and the other's was that when his drop down box was changed it would activate the event. In my case there is a seperate ID, the "Go" hyperlink I mentioned above, that needs to be activated once the drop down value is entered.
Below is a portion of the HTML code where drop down box options are located as well as the "GO" hyperlink.
<select name="classList" onchange="selectClass(this);"><option class=tblrow2 value="All" selected=selected>All Schedules</option>
<option value="A" >
Transactions-Financial
</option>
<option value="N" >
Transactions-Non-Financial
</option>
<option value="RB" >
Running Balance
</option></select>
<input type="hidden" name="classindx" id = "classindx" value="" />
Go
This is a portion of my code that modifies the dropdown box value.
'try to get form by ID
Set frm = ie.Document.getElementByID("myFormID")
'try to get form by name
If frm Is Nothing Then Set frm = ie.Document.getElementsByName("facilityFeeRepayForm").Item(0)
'Set ieButton = ie.Document.getElementById("classindx") Here I tried to treat the Go hyperlink like a button but that didn't work either.
If frm Is Nothing Then
Else
ie.Visible = True
For Each element In frm.elements
On Error Resume Next
Select Case element.Name
Case "classList": element.Value = "RB"
ie.getElementByID("classindx").FireEvent("onClick") 'nothing happens with this code
While ie.ReadyState <> 4: DoEvents: Wend
End Select
Next
End If
I would appreciate any help you can offer.
Thank you,
John
Instead of clicking the link, try this:
ie.Document.parentWindow.execScript "submitTransForm()", "JavaScript"

Saving checkbox state on form post problem

I'm having problems setting the unchecked state of checkboxes upon form post. I have over 1000 checkboxes and so far i am able to check each checkbox n save there checked state. My problem however is unchecking the checkboxes.
I'm not having problems saving the checked state of each checkbox after form is posted. My problem is unchecking values then having that unchecked state saved after form post.
I'm also using paging on the page as shown in the code below (Values of submit buttons are parameters of a stored procedure)-
<center><input id="buttonStyle" type="submit" name="Page" value="#">
<% for i = 97 to 122 %>
<input id="buttonStyle" type="submit" name="Page" value="<%=CHR(i) %>">
<% next %></center>
<input id="buttonStyle" type="submit" name="Page" value="View All">
I need to save my checked state as I view each letter. So far thanks to the help of shadowwizard I am able to save checked and unchecked states of checkboxes if I click view all button. However the problem now is that when i click another letter (e.g - a, b, c) any checked state is removed when clicking view all.
<%
Dim tempArray
Dim checkArray
Dim temphiddenArray
Dim hiddenArray
'CheckBox Selection Array
if len(Request.Form("selectedRecord")) > 0 then tempArray = split(Request.Form("selectedRecord"), ",")
if isarray(tempArray) then
redim checkArray(ubound(tempArray))
'Create CheckArray ARRAY
for i = lbound(tempArray) to ubound(tempArray)
checkArray(i) = trim(tempArray(i))
next
'Hidden Array check
if len(request.Form("hiddenArray")) > 0 then temphiddenArray = split(request.Form("hiddenArray"), ",")
if isarray(temphiddenArray) then
redim hiddenArray(ubound(temphiddenArray))
for i = lbound(hiddenArray) to ubound(hiddenArray)
hiddenArray(i) = trim(temphiddenArray(i))
Session("LastCheck_"&i) = hiddenArray(i)
next
if ubound(hiddenArray) >= ubound(checkArray) then
for i = lbound(hiddenArray) to ubound(hiddenArray)
Session("CheckBox_"&(Session("LastCheck_"&i))) = ""
next
end if
end if
for i = lbound(checkArray) to ubound(checkArray)
Session("CheckBox_"&checkArray(i)) = "Checked"
%>
<input type="hidden" name="hiddenArray" value="<%=checkArray(i) %>">
<%
next
else
Session("CheckBox_"&request.Form("hiddenArray")) = ""
end if
%>
<% while not objRS.EOF %>
<input type="checkbox" name="selectedRecord" value="<%=objRS("Id") %>" <%=Session("CheckBox_"&objRS("Id")) %>>
objRS.MoveNext
wend
You're going through whole forest instead of climbing a short tree, or in other words making something simple terribly complicated.
What you need is this function:
<%
Function WasCheckedByUser(id)
Dim x
WasCheckedByUser = "checked=""checked"""
For x=1 To Request.Form("selectedRecord").Count
If Trim(Request.Form("selectedRecord").Item(x))=Trim(id) Then
Exit Function
End If
Next
WasCheckedByUser = ""
End Function
%>
Then use it like this:
<input type="checkbox" name="selectedRecord" value="<%=objRS("Id") %>" <%=WasCheckedByUser(objRS("Id")) %>/>
No need in arrays, no need in Session variables. Just simple iteration over the posted values (which are the values of the checked checkboxes) and if certain value is there, it means the corresponding checkbox should be checked, otherwise leave it unchecked.
Edit: you lose the "state" because when you click specific letter, you send to the browser only part of the checkboxes - so the previous value is indeed "lost" for good.
The most simple way to fix that is to send all checkboxes to the browser - always - and using simple style hide those that you currently don't send at all.
So, you'll have to change the SQL used to populate objRS to always select all, and change the loop to this:
<%
Do Until objRS.EOF
Response.Write("<input type=""checkbox"" name=""selectedRecord"" value=""" & objRS("Id") & """ " & WasCheckedByUser(objRS("Id")))
If Len(Request.Form("Page"))=1 And Trim(Left(objRS("Id"), 1))<>Trim(Request.Form("Page")) Then
Response.Write(" style=""display: none;""")
End If
Response.Write(" />")
objRS.MoveNext
Loop
%>
As far as I can see it should work and now preserve the state even for the hidden checkboxes.
check the resulting source code to see what it generated.
From what I can see, one problem would be that only checked checkboxes are posted when you submit a form, so if you originally have 10 checkboxes and check 3 of them and post, only those 3 will post back (and from the code, I guess only those 3 checkboxes would display after you submit, all of them checked).
You'd need to save all the checkboxes in the first run (say, with a default empty value like space), and then just change their session values when they're checked
The checkboxes are they actual items such as a category or option?
The reason i ask is that if you're setting checkboxes, how are these checkboxes defined? are they static fields or are they dynamic. I hope dynamic.
Here's how you can get things going.
Create a table called news (newsid, newstxt)
Create a table called categories (catid, catxt)
Create a table called NewscatSelected (ncsid, newsid, catid)to store check boxes of selected categories with the related newsid
Checkbox page form (cb1.asp)
Send the newsid as a query string to page (cb1.asp?newsid=34)
Dynamically list all categories as checkboxes, and get all records from NewscatSelected and pair them up. Any items that exist in the table NewscatSelected will be checked. They will have the same name but with an underscore and the numeric value of the category (cbt_34) to distinguish them easily
3.
Update Page Form (cb2.asp)
Upon getting querystring delete any existing values for the newsid sent to avoid duplicates
Insert the new checked values into the table called "NewscatSelected"
Redirect back to (cb1.asp?newsid=34) and new values will be checked.
See image below
I just posed an answer to this problem here:
how to implement a check box in classic asp
It's specifically designed for non-sequentially numbered, dynamically created checkboxes which require passing both a unique ID value and either checked or unchecked.
The solution does require a hidden field for each check box, but it does not use Javascript or any client side programming.
As the previous answer states, checkboxes do not get posted back when they are unchecked, so you have nothing in the request object that represents unchecked ones, which is fine if you know everything you are expecting to be posted back, but if it's all dynamic then it's not much use.
One workaround i've used before is to use hidden fields for the actual data, and use the checkboxes to control (via JS) the value's of the associated hidden fields, however I don't know how that solution would perform if you have 1000's of them on a page!