I'm testing an XFA form with several sections that can be added or removed. These sections are implemented using subform "rows" containing various widgets, so my test object tree might contain:
where sfRow's afpid/SOM expression could be: xfa.form.form1.sfCalendar.sfWeek.sfRow
I would like to use a regular expression for the afpid property for the test object "sfRow" (and its children) so that I do not need to maintain sfRow_2 and other siblings, then use an alternate way (such as an index ordinal) to find the unique row or widget I'm interested in.
But as soon as I set the Test Object property "afpid" to any regular expression (apart from its original unescaped text), the object fails to match, eg. Highlight in application yields:
The selected object could not be highlighted.
In fact, some regular expressions, eg ".*sfRow\[\d\]" seem to cause my AcroQTP server (Adobe Reader) to enter a bad state and need restarting.
Why doesn't regular-expression matching work for afpid ?
Any suggestions how I can "collapse" all my row subforms?
After further experimentation, I have reached the following conclusions:
1) Yes, I can specify the "afpid" property as a regular expression in the object repository. I think I was confused by other symptoms.
2) I can use this regular expression to retrieve a count of the number of rows by calling the row's parent's ChildObjects():
Set objRowParent =PdfDoc
Set objRowHeader = objRowParent.AcroForm("sfHeader")
Set objRow = objRowParent.AcroForm("sfRow") ' where "afpid is a regexp like ".*sfRow\[\d+\]"
nChildren = objRowParent.ChildObjects().Count - 1
3) I can use that ChildObjects() call to iterate through the list of rows.
for i=1 to nChildren
Set objRow = objRowParent.ChildObjects()(i)
Set objRowChild = objRow.AcroField("SomeField")
txtAfpid = objRowChild.getTOProperty("afpid")
txtAfpid = MyRegexReplace( txtAfpid, "sfRow[\d+]", "sfRow["&i&"]" )
Call objRowChild.setTOProperty("afpid", txtAfpid )
Call objRowChild.setValue( "Blah" )
4) Once I change the afpid on a "sfRow" element to a hard-coded value, I cannot change it back to a regular expression.
5) Even if I didn't change the afpid of "sfRow" away from its original regexp, it seems I cannot trust the results of ChildObjects() after I add or delete rows (programmatically or manually at a breakpoint). Various RefreshObject()s did not help.
6) If I want to get Reader into a bad state, all I need to do is reduce the number of rows (manually or programmatically), then try accessing the members of the ChildObjects() collection that were deleted but still returned as part of the ChildObjects() collection.
7) Strangely, ChildObjects() does refresh its cached value if you ask for something beyond its collection.
Set objRow = objRowParent.ChildObjects()( nChildren )
objHeader.AcroButton("Add a row").Click
objHeader.AcroButton("Add a row").Click
print objRowParent.ChildObjects().Count-1 ' returns nChildren (wrong)
Set objRow = objRowParent.ChildObjects()( nChildren+1 )
print objRowParent.ChildObjects().Count-1 ' returns nChildren+2 (right)
So, I'm left with a lot of hackery where I need to manage the number of rows internally.
Could you please provide some guidance on how to programmatically count rows and access rows?
(I've tried to be reasonably diligent in my VB scripting here, but caveat emptor on any snippets provided above.)
I'm glad to hear that regexp matching is working for afpid!
I don't think that I can help you with the other problem. Perhaps you should start a dedicated thread for it. I don't understand what you mean by "change the afpid on a "sfRow" element ... back to a regular expression."
I am having the same trouble. Any help available? I have written code to simulate the OR highlight function. I use this code to investigate the OR recognition. I am curious why explicite strings work but regular expressions do not. Here is the code for my highlight routine.
' Declare APIs
Extern.Declare micHwnd, "GetDesktopWindow", "User32.DLL", "GetDesktopWindow"
Extern.Declare micULong, "GetWindowDC", "User32.DLL", "GetWindowDC", micHwnd
Extern.Declare micInteger, "ReleaseDC", "User32.DLL", "ReleaseDC", micHwnd, micULong
Extern.Declare micULong, "CreatePen", "Gdi32.DLL", "CreatePen", micInteger, micInteger, micDword
Extern.Declare micInteger, "SetROP2", "Gdi32.DLL", "SetROP2", micULong, micInteger
Extern.Declare micULong, "SelectObject", "Gdi32.DLL", "SelectObject", micULong, micULong
Extern.Declare micULong, "DeleteObject", "Gdi32.DLL", "DeleteObject", micULong
Extern.Declare micULong, "GetStockObject", "Gdi32.DLL", "GetStockObject", micInteger
Extern.Declare micULong, "Rectangle", "Gdi32.DLL", "Rectangle", micULong, micInteger, micInteger, micInteger, micInteger
Public Sub Highlight (Obj, Times)
' Get screen coordinates
X = eval(Obj.GetROProperty ("abs_x") )
Y = eval(Obj.GetROProperty ("abs_y") )
W = eval(Obj.GetROProperty ("width") )
H = eval(Obj.GetROProperty ("height") )
' Get Desktop DC
hDC = Extern.GetWindowDC (Extern.GetDesktopWindow)
' Create a three pixels wide Pen
hPen = Extern.CreatePen (6, 3, RGB(0, 0, 0)) ' PS_INSIDEFRAME, 3 , RGB(0, 0, 0)
Extern.SetROP2 hDC, 6 ' hDC, R2_NOT
Extern.SelectObject hDC, hPen
' Use an empty fill
Extern.SelectObject hDC, Extern.GetStockObject (5) ' NULL_BRUSH
'msgbox X & ", " & Y & ", " & W & ", " & H,,"X, Y, W, H"
for i = 0 to Times * 2 + 1
Extern.Rectangle hDC, X, Y,X+W, Y+H
wait 0, 100
Extern.ReleaseDC Extern.GetDesktopWindow, hDC
Highlight Window("Windows Internet Explorer").WinObject("Shell DocObject View").PDFDoc("PDF").AcroXFAForm("form").AcroXFAForm("coventryHealthc are").AcroXFAForm("page1").AcroXFAForm("sGHPMOHealthQuestionaire"), 15 'works because it references stored object in OR
Highlight Window("Windows Internet Explorer").WinObject("Shell DocObject View").PDFDoc("PDF").AcroXFAForm("form").AcroXFAForm("coventryHealthc are").AcroXFAForm("page1").AcroXFAForm("name:=sGHPMOHealthQuestionnair e","afptype:=subform","afpid:=xfa.form.coventryHealthcare.pag e1.sGHPMOHealthQuestionnaire"),15 'doesn't work. Actually removes recognition. 'Breaks' Object Spy Why?