Skip to main content
Fightergator
Inspiring
October 5, 2023
Answered

Endless Loop When Searching Documents in Framemaker

  • October 5, 2023
  • 3 replies
  • 971 views

I build an array of acronyms in the document's acronym glossary and use the getFind function below to search the document to see if the acronym is used and how many times it's used (findCtr++).  I'm running into some cases where the getFind function goes into an endless loop looking for specific words in specific documents.  This might happen with just four words in a document, or sometimes dozens of words.  The loop is 100% repeatable.  I believe I need to move the textRange.beg to the end of the "find" word each time a match is found, but I'm not familiar enough with ranges to know how to do it.  Appreciate any suggestions.

function getFind(findString, considerCase, docName) {  

    doc=app.ActiveDoc; //sets the active document as the object
    docStart = doc.MainFlowInDoc.FirstTextFrameInFlow.FirstPgf;
    textRange = app.ActiveDoc.TextSelection;

    findParams = AllocatePropVals (5);

    propVal = new PropVal ();
    propVal.propIdent.num = Constants.FS_FindText;
    propVal.propVal.valType = Constants.FT_String;
    propVal.propVal.sval = findString;
    findParams[0] = propVal;
    
    propVal = new PropVal ();
    propVal.propIdent.num = Constants.FS_FindCustomizationFlags;
    propVal.propVal.valType = Constants.FT_Integer;
         if (considerCase) {
            propVal.propVal.ival = Constants.FF_FIND_CONSIDER_CASE; 
            } else {
            propVal.propVal.ival = 0; }
    findParams[1] = propVal;

    propVal = new PropVal ();
    propVal.propIdent.num = Constants.FS_FindCustomizationFlags;
    propVal.propVal.valType = Constants.FT_Integer;
    propVal.propVal.ival = 16; // Regular expressions (per RQ)
    findParams[2] = propVal;
    
    propVal = new PropVal ();
    propVal.propIdent.num = Constants.FS_FindWrap;
    propVal.propVal.valType = Constants.FT_Integer;
    propVal.propVal.ival=0;
    findParams[3] = propVal;

    propVal = new PropVal ();
    propVal.propIdent.num = Constants.FS_RegexFlavour;
    propVal.propVal.valType = Constants.FT_Integer;
    propVal.propVal.ival = Constants.FR_USE_PERL;  //1; 
    findParams[4] = propVal;
  
    textRange = doc.Find(textRange.beg, findParams);
    checkAcronyms();
}

function checkAcronyms() {
    while (textRange.beg.obj.ObjectValid() && FA_errno == Constants.FE_Success) {  
        var find = getText (textRange, doc) // Matching acronym found
            if (find.length > 0) {
                findCtr++; // Count times word is found
            } 
       textRange = doc.Find(textRange.beg, findParams);
    }
    return;
}

 

    This topic has been closed for replies.
    Correct answer frameexpert

    I used to see this when I first started scripting with FrameScript. So I never felt comfortable trusting the Find method. My way of doing it is to loop through the body page paragaphs, and for each paragraph, get the text and use a regular expression to search the text. If I actually need to manipulate the text, then I use doc.Find (), starting with a TextLoc of the paragraph and offset of the found text. I don't have time to post code right now, but will try to tomorrow.

    3 replies

    frameexpert
    Community Expert
    frameexpertCommunity ExpertCorrect answer
    Community Expert
    October 6, 2023

    I used to see this when I first started scripting with FrameScript. So I never felt comfortable trusting the Find method. My way of doing it is to loop through the body page paragaphs, and for each paragraph, get the text and use a regular expression to search the text. If I actually need to manipulate the text, then I use doc.Find (), starting with a TextLoc of the paragraph and offset of the found text. I don't have time to post code right now, but will try to tomorrow.

    Fightergator
    Inspiring
    October 6, 2023

    Thanks Rick...I've thought about your method of searching by pgf since we spoke last year, and have often considered trying to implement it.  However, I have two concerns.  I currently search for over a thousand words & terms, running the entire search list one time for each document.  Doing it pgf by pgf, I'd have to run the entire search list for each pgf.  Wouldn't that  increase processing time considerably.  Also, will it search tables natively, or would a separate cell by cell search function need to be run.  One possible advantage of my current search method is that it searches tables & pgfs without a separate function.  I'm certain your method is more reliable and I certainly appreciate any code you have time to share. 

    frameexpert
    Community Expert
    Community Expert
    October 10, 2023

    I am uploading a series of videos to YouTube that explain how I do finds/changes with FrameMaker ExtendScript. The videos aren't edited or polished, but they will give you useful information. Search for FindChange with FrameMaker ExtendScript on YouTube. I will upload more later today.

    Bob_Niland
    Community Expert
    Community Expert
    October 5, 2023

    You may already have the answer, but if not, also look for any possible looping structures in the document itself: circular Xrefs, Text Insets with refs to the importing doc, etc.

    FM does not try to prohibit these, and generally avoids its own ∞loops by doing only one pass per Update click.

    Fightergator
    Inspiring
    October 6, 2023

    Bob, thanks for tip on searching for looping structures.  I tried that using Insert > Index > Of References, but it came up blank.  In one book, the only place I have a problem is the LOT document.  I updated the book, to include the LOT, but still no luck.  In that book, it only goes into an endless loop on four out of 322 search words, all four of which are found once or twice in the LOT.   In another book, the endless loops occur in one of the chapter documents and involve about 25 words.  I haven't checked that chapter for cross references yet...but will. 

    K.Daube
    Community Expert
    Community Expert
    October 5, 2023

    It's my guess, that 

    textRange = doc.Find(textRange.beg, findParams);

    Does not advance the start point for the next search and you always find the same item..

    (I have not access to my own search scripts now to give a better advice).

    Fightergator
    Inspiring
    October 5, 2023

    Thanks Klaus for confirming my suspicion.  I have a couple of your search scripts I'll look over and see if I can figure out how to advance the start point after each search. I suspect that would also speed up my searches. 

    K.Daube
    Community Expert
    Community Expert
    October 6, 2023

    If you want to stay with the Find method:

    Russ Ward created the term "lets jimmy the text range" in his post. Although his post is for replacement, the method to go forward is the same for searching.

    tr.beg.offset += sFound.length; // lets jimmy the text range in memory