I want to use VBScript to click a button that reads “Add Document” in the GUI of an application that runs in Internet Explorer. The problem is there is no “id”, “name” , or “class” element in the source code (see below) to use as a reference in the script.
Source Code:
<TD>
<INPUT type="button" value="Add Document" onclick="addFileUploadBox()">
</TD>
My code is below and works for elements that have source code ids. Also included are some failed attempts to click the button in question based on my googling but I cant get to work. I'm new to this and any help would be appreciated - any suggestions to fix?
My Code:
Dim objIE
Set objIE = CreateObject("InternetExplorer.Application")
objIE.Visible = True
objIE.Navigate "http://sharemxxxx.xxxxx.com/xxxImport/import.aspx"
While objIE.Busy
WScript.Sleep 100
Wend
objIE.Document.getElementById("txtReferenceNum").value = "15226002"
objIE.Document.getElementById("ddlCategory").value = "05"
objIE.Document.getElementById("btnRetrieve").click
' ABOVE CODE WORKS
' NOT WORKING #1 - DOES NOTHING - NO ERROR
'===========================================
objIE.Document.getElementByType("btn").Value="Add Document"
For Each btn In objIE.Document.getElementsByTagName("input")
If btn.Value="Add Document"Then btn.Click()
Next
' NOT WORKING #2 - DOES NOTHING - NO ERROR
'===========================================
For Each Button In objIE.Document.getElementsByTagName("input")
If Button.Value="Add Document"Then Button.Click()
Next
' NOT WORKING #3 - DOES NOTHING - NO ERROR
'===========================================
Set oInputs = objIE.Document.getElementsByTagName("input")
For Each elm In oInputs
If elm.Value = "Add Document" Then
elm.Click
Exit For
End If
Next
' NOT WORKING #4 - Show Empty Msg Box
'===========================================
set objButtons = objIE.document.getElementsByTagName("input")
for each objButton in objButtons
strText = objButton.innerhtml
msgbox strText
if (strText = "Add Document") then
msgbox "found the button!"
objButton.click
exit for
end if
next
You probably don't even need to find the element. It looks like the button just calls a JavaScript function. So you can use the execScript() function to run it.
For example:
objIE.Document.parentWindow.execScript "addFileUploadBox();", "javascript"
Related
i need to write a text area (box) value to .txt i am getting permissions denied when writing to "input.txt"
i got got permission denied when writing input.txt from the text box. i edited using suggestions found below and also killed handle for input.txt using process explorer.
using the code below i can now save textbox text to text file input.txt.
i also figured out how to call upon a batch file to change that text into a cyphered form, and then i added a refresh button to open that changed text into a second textbox as a final output result which leaves the text now capable of being password encrypted after being saved in input.txt and opened in a second textbox from file SR-Encrypted.txt after being cyphered via batch file encrypter.bat then by refreshing the page using the refresh button i added..
thank you agnar!
<html>
<script language="vbscript">
option explicit
Const ForWriting = 2
Dim objFSO, objFile, strFileName, objshell
strFileName = "input.txt"
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objShell = CreateObject("WScript.Shell")
Sub Submitarea
Set objFile = objFSO.OpenTextFile(strFileName, 2, True)
objfile.Write TextFile.Value
objFile.Close
MsgBox "Your text has been added to " & strFileName, 64, "Textarea Input"
End Sub
</script>
</html>
</head>
<title>Example</title>
<script language="VBScript">
Sub test
set oFSO=CreateObject("Scripting.FileSystemObject")
set oFile=oFSO.OpenTextFile("SR-Encrypted.txt",1)
text=oFile.ReadAll
document.all.ScriptArea.value=text
Set objFile = nothing
oFile.Close
End Sub
</script>
</head>
<script language="vbscript">
Option Explicit
' This is the Sub that opens external files and reads in the contents.
' In this way, you can have separate files for data and libraries of functions
Sub Include(yourFile)
Dim oFSO, oFileBeingReadIn ' define Objects
Dim sFileContents ' define Strings
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oFileBeingReadIn = oFSO.OpenTextFile("try.vbs", 1)
sFileContents = oFileBeingReadIn.ReadAll
oFileBeingReadIn.Close
ExecuteGlobal sFileContents
End Sub
' Here we call the Include Sub, then pass it the name of the file we want items from
Include "mySubLib"
</script>
<body>
<button onClick="test()">Refresh Message Encrypter-Decrypter</button>
</body>
</html>
</head>
</html>
<body>
<h1>Write File</h1>
<p>How to Write to a File.</p>
<textarea name="TextFile" id="TextFile" rows="20" cols="50"></textarea>
<input type="button" value="Submit" onclick="Submitarea">
</body>
<body>
</body>
</html>
The "permission denied" errors most likely occur because the file had already been opened. Open the file only when you actually want to write to it, and close it right away after you finished writing. Also, if you want to write the content of the text area to the file you need to actually write the content of the text area, not the string "Txtarea".
Change this:
Set objFile = objFSO.OpenTextFile(strFileName, 2, True)
Set objShell = CreateObject("WScript.Shell")
Sub Submitarea
sTxtarea = TextFile.Value
objfile.Write "Txtarea" & vbCrLf
MsgBox "Your text has been added to " & strFileName, 64, "Textarea Input"
End Sub
to this:
Set objShell = CreateObject("WScript.Shell")
Sub Submitarea
Set objFile = objFSO.OpenTextFile(strFileName, 2, True)
objfile.Write TextFile.Value
objFile.Close
MsgBox "Your text has been added to " & strFileName, 64, "Textarea Input"
End Sub
and the problem will disappear.
Change the second parameter of the OpenTextFile() method from 2 to 8 if you want to append to the output file rather than replace its content.
#ansgar wiechers edits and suggestions were all correct and resulted in the scripts functioning properly. see code above in question for accurate solution to the original question.
permissions denied were caused by an open handle on input.txt. using process tree i killed the handle and the file functions properly.
the suggestion posted by ansgar wiechers fixed the code which was another separate issue but the correct codes and information reguarding the original question are in the post. thank you.
what Im trying to do is very simple. A GPO that runs a cloud-based install once. I just cannot find the correct VB syntax to simply click on a button on a webpage that starts an installation. I have a runonce batch file in a GPO that calls the vbs file which currently contains...
Sub test()
With CreateObject("InternetExplorer.Application")
.Visible = True
.Navigate "http://xxxxxxx.com"
Do While .Busy Or .readyState <> 4
WScript.Sleep 50
Loop
Set oInputs = .Document.getElementsByTagName("input")
For Each elm In oInput
If elm.Value = "the HTML has no valued or ID" Then
elm.Click
Exit For
End If
Next
Do While .Busy Or .readyState <> 4
WScript.Sleep 50
Loop
End With
End Sub
The HTML element i am trying to trigger is...
<a class="button" onclick="DownloadSubmit();" href="" target="_blank"></a>
I've got a simple program than scans data into a spreadsheet along with a timestamp, then you can either update the data by saving, or quit and exit and save.
The only issue I've been stuck on for a day or so is to work around the error handling of the case of the spreadsheet being already open. Id like to have something like this;
if file is open THEn msgbox("File is open, close file and start again")
WScript.Quit
Option Explicit
DIM oFs: Set oFs = CreateObject("Scripting.FileSystemObject")
DIM objExcel, strExcelPath, objSheet
DIM ib
DIM msg1
DIM msg2
strExcelPath = "c:\temp\Example.xls"
Set objExcel = CreateObject("Excel.Application")
objExcel.WorkBooks.Open strExcelPath
Set objSheet = objExcel.ActiveWorkbook.Worksheets(1)
DO
ib=inputbox("SCAN NAME, SCAN LOTS"&vbCrLf&"TO UPDATE,SCAN ""UPDATE."""&vbCrLf&"TO EXIT, SCAN ""QUIT.""","Picklot Passout Database")
IF ib="" THEN
msg1=MsgBox("You must scan either a NAME or LOT NUMBER."&vbCrLf&"If you want to exit, scan QUIT."&vbCrLf&"Click OK to continue.",vbokonly,"Cannot Insert Blank Data")
ELSEIF ib= "QUIT" OR ib= "quit" THEN
objExcel.ActiveWorkbook.Save
objExcel.ActiveWorkbook.Close
objExcel.Application.Quit
set objExcel = Nothing
Set oFs = Nothing
ELSEIF ib="update" OR ib="UPDATE" THEN
objExcel.ActiveWorkbook.Save
msg2=MsgBox("Update Complete.",vbokonly,"Database Updated")
ELSE
objSheet.Range("A2").EntireRow.Insert
objSheet.Cells(2, 1).Value = ib
objSheet.Cells(2, 2).Value=(now)
END IF
LOOP WHILE NOT ib="quit" AND NOT ib="QUIT"
This may help point you in the right direction. Sorry for the rushed, lowercase syntax and unconventional indentations (do not follow my bad practice - keep yours! :D), I wrote it in notepad you see - but it has been tested successfully.
Anyhow, with reference to your code, I have restructured it in a bad manner, familiar to me, adding the functionality you specify. Essentially the task manager application list is checked for a running instance of the "example" Excel file (depending on what version of excel you're using the syntax will differ).
If found it will make it the active window (thereby preventing a read only duplicate instance initiating). If no instance is found it will open "example.xlsx", in this case using a relative path to the script itself. A subroutine is then called to do the business with the cells...
I have written it in such a way to try keep your specs as well as maintain the "OK" and "Cancel" buttons explicitly functional. Please feel free to tinker with this, you may need to address the path and instr lines differently. I hope it helps! All the best.
path=createobject("scripting.filesystemobject").getparentfoldername(wscript.scriptfullname)
excelpath=path&"\example.xlsx"
set objword=createobject("word.application")
set coltasks=objword.tasks
i=0
for each objtask in coltasks
name=lcase(objtask.name)
if instr(name, "microsoft excel - example") then
i=1
end if
next
if i=1 then
wscript.echo "An active instance of ""example.xlsx"" has been found"
set objexcel=getobject(excelpath)
call UPDATER
else
set objexcel=createobject("excel.application")
objexcel.workbooks.open(excelpath)
set objsheet=objexcel.activeworkbook.worksheets(1)
objexcel.visible=true
call UPDATER
end if
sub UPDATER
do
data=inputbox("Please enter data" &vbcrlf&vbcrlf& "To save data & continue, type ""update""" &vbcrlf& "To save data & exit, type ""quit""","Excel DB Updater")
if isempty(data) then
objexcel.activeworkbook.close
objexcel.application.quit
wscript.quit()
elseif lcase(data)="quit" then
objexcel.activeworkbook.save
objexcel.activeworkbook.close
objexcel.application.quit
quit=msgbox("DB Updating complete",vbokonly,"Excel DB Updater")
wscript.quit
elseif lcase(data)="update" then
objexcel.activeworkbook.save
update=msgbox("Data save complete, press OK to continue",vbokonly,"Excel DB Updater")
elseif len(data)<>0 then
objsheet.range("A1").entirerow.insert
objsheet.cells(1, 1).value=data
objsheet.cells(1, 2).value=(now)
add=msgbox("Data added, press OK to continue",vbokonly,"Excel DB Updater")
end if
loop while len(data)>=0 and not lcase(data)="quit"
end sub
Guys
I just wrote a vbs code snippet to automatically post in a forum. That's just for convenience. I encountered a wired problem:
I have several accounts. When I login as some accounts and use the script to automatically post, everything is OK. However, when I login as the other accounts and run the script, I got the error:
Error : Object required "getElementById(...)"
Code : 800a01a8
Source : Microsoft VBScript runtime error
I'm sure the object exists because I get it in the source of the webpage. I feel the error occurred randomly and I cannot get the regularity.
The script is ran in a Windows 8 OS and the browser is IE9. I'm a new learner of vbs and I don't know how to debug it. So I hope someone can help me. You can give me some clue.
Here is my code snippet:
Option Explicit
Dim IEApp
Dim iURL1
Dim iURL2
Dim iURL3
Dim iURL4
Dim iURL5
Set IEApp = CreateObject("InternetExplorer.Application")
iURL1="http://bbs.dealmoon.com/thread-299027-1-1.html"
iURL2="http://bbs.dealmoon.com/thread-299195-1-1.html"
iURL3="http://bbs.dealmoon.com/thread-299018-1-1.html"
iURL4="http://bbs.dealmoon.com/thread-299015-1-1.html"
iURL5="http://bbs.dealmoon.com/thread-299014-1-1.html"
Open iURL1
Open iURL2
Open iURL3
Open iURL4
Open iURL5
WScript.Echo("Done!")
Sub Wait(IE)
Do
WScript.Sleep 500
Loop While IE.ReadyState < 4 And IE.Busy
Do
WScript.Sleep 500
Loop While IE.ReadyState < 4 And IE.Busy
End Sub
Sub Post(IE)
Dim count
For count=0 To 9
With IE.Document
.getElementById("fastpostmessage").innerHTML = "good"
.getElementById("fastpostsubmit").click
Wait IE
WScript.Sleep GetRandom(7,15)
End With
Next
End Sub
Sub Open(PageURL)
IEApp.Visible = False
IEApp.Navigate PageURL
Wait IEApp
Post IEApp
End Sub
Function GetRandom(floor,ceil)
Randomize
GetRandom=Int((ceil - floor + 1) * Rnd + floor)*1000
End Function
You should call your POST routine after all the HTML content is loaded, for example in DOMContentLoaded or window.onload (for IE<9).
You dimmed IEApp, created the object, but you are not using it when trying to get the element ID. Your With block should look like this:
With IEApp.Document
.getElementById("fastpostmessage").innerHTML = "good"
.getElementById("fastpostsubmit").click
Wait IEApp
WScript.Sleep GetRandom(7,15)
End With
There are a few other places you only have IE instead of IEApp. Clear those up and your code should run fine.
I have a weird problem with QTP 11. The following piece of code worked so far, but suddenly stopped working and throws Object does not support this property or method.: 'objPage.Link' for the line with 'if link exist'
Set objBrowser = Browser("creationtime:=" & Desktop.ChildObjects(oDesc).Count - 1 & "")
Set objPage = objBrowser.Page("title:=.*")
If objPage.Link("class:=menu_link_tab_.*", "html id:=.*DesktopTab").Exist(3) Then
msgbox "ok"
End If
Can anyone tell me what is wrong and/or how to do it right?
EDIT: I solved this but still have no idea what happened. I just cut this part from QTP script and pasted it into Notepad and then copied it from Notepad to QTP. Everything works fine. I did not change anything... Any ideas what the hell happened are welcomed.
ANOTHER EDIT: The problem reappears randomly. With no changes to anything I can just run the test 10 times to have it fail randomly with the 'Object does not support this property or method' message
I have a startBrowser function where I set the objPage and objBrowser :
Function startBrowser(vURL)
Dim oDesc
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = True
IE.Navigate vURL
Window("hwnd:=" & IE.HWND).Maximize
Set oDesc = Description.Create
oDesc( "micclass" ).Value = "Browser"
If Desktop.ChildObjects(oDesc).Count > 0 Then
Set objBrowser = Browser("creationtime:=" & Desktop.ChildObjects(oDesc).Count - 1 & "")
End If
Set objPage = objBrowser.Page("title:=.*")
End Function
I have added lots of msgboxes with GetROProperty to verify whether the objects are ok. They seem to be.
Now my function to click the link looks like this :
Function clickMainMenuLink(vIdentifier)
Set objLink = objPage.Link("class:=menu_link_tab_.*", "html id:=.*" & vIdentifier, "index:=0")
If objLink.Exist(timeOut) Then
objLink.Click
Else
reporter.ReportEvent micFail, "Click the " & vIdentifier & " menu link", "Cannot find the " & vIdentifier & " menu link"
ExitTestIteration
End If
End Function
So at the moment my test just opens the browser and clicks a link as I try to debug the thing, but it still fails or passes randomly. The run error indicates line with 'Set objLink'. Any ideas for further debugging? I'm on QTP11 and IE8 if it matters.
From your error does not support this property or method: objPage.Link it would appear that the problem isn't with the .Exist part of line but the .Link part (you can verify this by separating the line into two lines and see which fails
set objLink = objPage.Link("class:=menu_link_tab_.*", "html id:=.*DesktopTab")
If objLink.Exist(3) Then
From your comment it seems that you're creating objPage in a different location from where you're using it, I suggest making sure that the object arrives OK.
Thanks Motti, your reasoning was right. The problem was with the objPage part. Despite the fact that I could read every property of objPage in a function QTP sometimes just did not see this objPage as a Page object. I guess it has something to do with not declaring type explicitly, but that's just a guess. As a dirty workaround I set up the objBrowser and objPage in every function now and it works 100%.