• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Telling Find method NOT to wrap

Advocate ,
Feb 11, 2012 Feb 11, 2012

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

TOPICS
Scripting

Views

3.0K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Feb 12, 2012 Feb 12, 2012

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
Feb 12, 2012 Feb 12, 2012

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Feb 13, 2012 Feb 13, 2012

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Feb 13, 2012 Feb 13, 2012

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
Feb 13, 2012 Feb 13, 2012

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Feb 13, 2012 Feb 13, 2012

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
Feb 13, 2012 Feb 13, 2012

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;

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Feb 13, 2012 Feb 13, 2012

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 ;
}

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Feb 10, 2020 Feb 10, 2020

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 "&amp;" 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.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Feb 10, 2020 Feb 10, 2020

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);

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Feb 12, 2020 Feb 12, 2020

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Feb 13, 2020 Feb 13, 2020

Copy link to clipboard

Copied

LATEST

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')
	)
);

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines