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%.
Related
I'm making some changes to a program that was written by another developer, which uses an SSDB Grid.
I'm writing the code for the BeforeUpdate method.
On Error GoTo BeforeUpdate_Err
Dim ans%
ans% = MsgBox("These changes will be committed to the database. These changes cannot be undone. " & _
"Would you like to continue?", vbYesNo, "Confirm Changes")
If ans% = 7 Then
Grd_Collection.CancelUpdate
End If
Exit Sub
BeforeUpdate_Err:
MsgBox (Err.Description)
The only other code for the grid is the InitColumnProps method.
However, after hitting the Exit Sub line, I get an error message "Update Error".
I've searched the code for this being hard-coded but it isn't, so it's coming from the grid.
What is causing the error and how do I fix it?
Doesn't the BeforeUpdate method pass in an integer? (Cancel As Integer) or something?
Therefore, you should just be able to change your code (and tidy it up) to this:
On Error GoTo BeforeUpdate_Err
If MsgBox("These changes will be committed to the database. These changes cannot be undone. " & _
"Would you like to continue?", vbYesNo, "Confirm Changes") = vbNo Then
Cancel = 1
End If
Exit Sub
BeforeUpdate_Err:
MsgBox (Err.Description)
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"
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.
So I'm having a problem with Crystal Reports where the first time I try to run the report, the report shows up empty. The report shows up with the various separators, lines, boxes, etc., but no data to fill in the report. I'm using Visual Basic 6 for the coding. I'm using a lot of inherited code and the code that handles the actual Crystal Reports is a file that is used for other reports and it works fine. So I'm sure the problem is from what I've done where I'm messing something up.
Here is the code I have so far:
Dim rs As ADODB.Recordset
Dim strRptFilePathTemp As String
Dim strRptFileName As String
Dim cSql As String
cSql = "SELECT * FROM TABLE1"
Set rs = DbConn.runStatement(cSql, "rs call", , , , , , , , , , True) 'gets a recordset based on the sql statement above
On Error GoTo ErrHandler
strRptFileName = "ReportName.rpt"
strRptFilePathTemp = App.Path
Screen.MousePointer = vbHourglass
Set frmcrystalreport.ReportRS = rs
DoEvents
frmcrystalreport.reportfile = strRptFilePathTemp & strRptFileName
frmcrystalreport.ReportTitle = _
frmCrystalReportsMainForm.GetRptTitle1("ReportTitle, ") & vbCrLf
gblStrReportFileNameLastRun = frmcrystalreport.reportfile
Screen.MousePointer = vbDefault
DoEvents
frmcrystalreport.Show vbModal
If Not frmcrystalreport.ReportRS Is Nothing Then
frmcrystalreport.ReportRS.Close
Set frmcrystalreport.ReportRS = Nothing
End If
Exit Sub
End If
End Sub
I've tried playing around with the DoEvents function to see if that can help but haven't had much luck with it. Everything works fine after that initial failed attempt at running the report. As long as I don't exit the program, it will print out a report with the valid data once I get passed that blank report. Thanks for any help you guys can give me.
Hmmm, it has been a while since I used VB6 and CR but I sort of remember that your need to discard the saved data before setting the viewers report source
Report.DiscardSavedData
CRViewer1.ReportSource = Report
Just figured out the problem after stumbling upon something in Crystal Reports. I had to turn off the save data with report feature in the report file under the File menu.