Copy link to clipboard
Copied
Hello,
I cannot make sense of the parameters to use for the doc.Find() method. I have succesfully created an array of parameters, but it seems impossible to set the param for FS_FindWrap to 0. According to the ExtendScript documentation, this parameter is expected as a "flag" that tells the Find method whether or not to wrap when the end of the document is reached. But as the params array only allows PropVals and there is NO definition of FT_Boolean of FT_Flag or something similar, I tried to use FT_Integer and assign the value 0 to it. The point is that this value is simply refused. It does NOT get set and the resulting ival of the parameter shows "ssval does not have a value".
I REALLY need this parameter and I need the Find() method to do what it is supposed to do, but FM is making it impossible. Is this a bug or am I doing something wrong here ?
Help !!!
Jang
Copy link to clipboard
Copied
Hi Jang,
I only did this in FDK. And it works like this
F_PropValsT findParams ;
findParams = F_ApiAllocatePropVals(1);
findParams.val[0].propIdent.num = FS_FindWrap;
findParams.val[0].propVal.valType = FT_Integer;
findParams.val[0].propVal.u.ival = FALSE;
F_TextRangeT trFound = F_ApiFind(m_docId, &textrange.beg, &findParams);
If end of document is reached and nothing is found, trFound is noch valid (all members are 0)
So in ExtendScript it shoud work something like this:
var findParams = new PropVals();
var findParam = new PropVal()
findParam.propIdent.num = Constants.FS_FindWrap;
findParam.propVal.valType = Constants.FT_Integer;
findParam.propVal.u.ival = false;
findParams.push(findParam) ;
var trFound = app.ActiveDoc.Find(textrange.beg, findParams);
BTW: ssval is null or empty, because this is an integer value, which you could get and set at ival (boolean == integer 0 or 1, so there's no need for FT_Boolean)
Hope this helps
Markus
Copy link to clipboard
Copied
Hello Markus,
Thanks for the help but the problem is that there is NO object propVal.u let alone propVal.u.ival. And if I try to set propVal.ival = 0, nothing happens. So I am slowly getting to the belief that this is a bug in FM10's ExtendScript.
I have found a workaround though, with some help from Rick: I push all the found textranges into an array until I find a textrange that has the same textlocs as the first one found. At that point, I know I have wrapped around and I exit the loop. The important thing about pushing the textranges into an array is that making the change to the textrange potentially changes the offsets, which makes it impossible to find the wraparound item. I now process all the textranges after I break out of the find loop.
It is a hassle, though. It should be easier. It should work.
Ciao
Jang
Copy link to clipboard
Copied
Hi Jang,
this snippet works for me. propVal in ES has no u. it has ival or sval directly.
var doc = app.ActiveDoc;
var range = doc.TextSelection;
var propVals = new PropVals() ;
var propVal = new PropVal() ;
propVal.propIdent.num = Constants.FS_FindWrap ;
propVal.propVal.valType = Constants.FT_Integer;
propVal.propVal.ival = 0 ;
propVals.push(propVal);
propVal = new PropVal() ;
propVal.propIdent.num = Constants.FS_FindText ;
propVal.propVal.valType = Constants.FT_String;
propVal.propVal.sval = "Test" ;
propVals.push(propVal);
for (var i=0 ; i < 5; i++)
{
var findrange = doc.Find (range.end, propVals);
if (findrange.beg.obj.ObjectValid() ==false)
{
alert("Text not found: " + i) ;
break ;
}
else
range = findrange ;
}
if I set FS_FindWrap to 1, it finds the word "Test" 5 times in my sample document.
If I set FS_FindWrap to 0, it finds the word "Test" once in my sample document
So i think this should work, at least in my small tests
Markus
Copy link to clipboard
Copied
BTW:
FS_FindWrap doesn't mean "Stop at the end of a document", it means "Stop if text range is reached, where search began":
That's what FDKref says:
FS_FindWrap
A BoolT flag that determines whether the find operation will
wrap when it reaches the location where the search began. Default
is True; the find operations wraps.
If False, after reaching the location where the search began, the
find operation returns an empty F_TextRangeT and
FA_errno is set to FE_NotFound.
So if you don't want a document wrap, you have to get last Textrange in doc (i.e. end of last paragraph) and compare findresult with this and cancel search. But that's a little bit tricky.
Markus
Copy link to clipboard
Copied
Hi Markus,
I have tried again by creating two new propVal items. I have been using AllocatePropVals ( 2 ). Same result: no value gets set for ival. Using FM 10.0.2.419. Which version of FM are you using ?
Oh, and I do know that the find wraps around to where it started - I am setting the start location to the first Pgf in the document just so that I know what is going on when testing...
Ciao from Uppsala - trying to make the customer happier...
Jang
Copy link to clipboard
Copied
Hi Jang,
I run 10.0.2.419, too, in German version, but in my experiences language version doesn't matter at that point.
I run exactly that code I posted here, without any modifications. But I used new PropVals() instead of AllocatePropVals().
Allocation is done with "new" in ExtendScript/JavaScript. May be that could be the problem.
If that doesn't work please post your snippet and I'll go into that one.
Markus
Copy link to clipboard
Copied
Hi Markus,
Here is the piece of code I tried. After these lines, the string value in params[0] is set, but the integer in params[1] not.
var params = AllocatePropVals ( 2 );
params[0].propIdent.num = Constants.FS_FindMarkerOfType;
params[0].propVal.valType = Constants.FT_String;
params[0].propVal.sval = "Conditional text";
params[1].propIdent.num = Constants.FS_FindWrap;
params[1].propVal.valType = Constants.FT_Integer;
params[1].propVal.ival = 0;
Copy link to clipboard
Copied
Hi Jang,
this code works for me. It's nearly the same than above. Because I've got a German FM running "Conditional text" is "Bedingter Text", and with that I tested it.
Don't use AllocatePropVals, use new PropVals() and new PropVal() instead.
Hope this works for you
Markus
var doc = app.ActiveDoc;
var range = doc.TextSelection;
var propVals = new PropVals() ;
var propVal = new PropVal() ;
propVal.propIdent.num = Constants.FS_FindWrap ;
propVal.propVal.valType = Constants.FT_Integer;
propVal.propVal.ival = 0 ;
propVals.push(propVal);
propVal = new PropVal() ;
propVal.propIdent.num = Constants.FS_FindMarkerOfType ;
propVal.propVal.valType = Constants.FT_String;
propVal.propVal.sval = "Conditional text" ;
propVals.push(propVal);
for (var i=0 ; i < 5; i++)
{
var findrange = doc.Find (range.end, propVals);
if (findrange.beg.obj.ObjectValid() ==false)
{
alert("Document searched: " + i + " matches") ;
break ;
}
else
range = findrange ;
}
Copy link to clipboard
Copied
This is still failing for me. If I look at propVal[0].propVal.valType in the data browser, it shows "1" which is correct for an integer. However, the iVal gives an error that "ssval does not have a value". Additionally, if you try something recursive, like replace "&" with "&" and update the text location with an offset of the location of the last find + the string length of the replacement string, the loop becomes infinite and the returned text range continues to point at the first instance for that paragraph (rather than the second instance which is past the offset).
I still think that the doc.Find() has a bug that doesn't respect the text location that you pass it.
Copy link to clipboard
Copied
Before each find, try setting the document's TextSelection property to the TextLoc you want to start the search from.
doc.TextSelection = new TextRange (textLoc, textLoc);
Copy link to clipboard
Copied
Jang, I run into the same problem when working with footnotes.
I had to remember the current location and stop the find process after traversing this again.
As Rick points out, i try to avoid the Find method, but it is the only method to get things in the order the user sees them. Other method present the order of creation.
function Fno_FindNextEnXref (oDoc, oUserLoc, sXRefFmt) { //=== Find next xref to endnote ===============
// Arguments oDoc Document receiving the XRef
// oUserLoc Current location where the user wants to place the EN reference
// sXRefFmt Cross reference format of xref to endnote
// Returns XRef object or null
// Attention NoWrap in the Find parameters has no effect - need to find wrap 'manually'
var IDcurrent, IDfound, jPgf = 1, jThis, jFound, k,
oFindParams, oPgf, oPgfEnd, oPgfStart, oTL, oTRfound, oXRef, oXRefTI;
oTL = oUserLoc.txtRange.beg; // current cursor location
oFindParams= Fno_GetFindParameters (8, sXRefFmt); // find XRef forwards, NoWrap not working
oTRfound = oDoc.Find(oTL, oFindParams);
if (oTRfound.beg.obj.ObjectValid()) {
oXRefTI = oDoc.GetTextForRange (oTRfound, Constants.FTI_XRefBegin); // one 1 item in array
for (k = 0; k < oXRefTI.length; k++) { // k always 0 nevertheless loop necessary!
oXRef = oXRefTI[k].obj;
break;
}
}
if (oXRef == undefined) {return null; } // no XRefs at all in Doc
// --- Check whether there was a wrap around
IDcurrent = oTL.obj.id; // ¶ of current location
IDfound = oXRef.TextRange.beg.obj.id; // ¶ of found XRef
oPgfStart = oDoc.MainFlowInDoc.FirstTextFrameInFlow.FirstPgf;
oPgfEnd = Fno_GetLastPgfInMainFlow (oDoc);
oPgf = oPgfStart;
while (oPgf.ObjectValid() ) {
if (IDcurrent == oPgf.id) {jThis = jPgf;}
if (IDfound == oPgf.id) {jFound = jPgf;}
oPgf = oPgf.NextPgfInFlow;
jPgf += 1;
if (jThis != undefined && jFound != undefined) {break}
}
if (jFound >= jThis) { return oXRef;} // Next XRef found after current location
return undefined; // No XRef after the current location
} //--- end Fno_FindNextEnXref
Copy link to clipboard
Copied
Just to throw in my two cents, here is the syntax I prefer for declaring PropVals explicitly:
var myProps = new PropVals(
new PropVal(
new PropIdent(Constants.FS_FindWrap),
new TypedVal(0)
),
new PropVal(
new PropIdent(Constants.FS_FindText),
new TypedVal('text')
)
);