Skip to main content
Community Expert
November 26, 2025
Question

Search/replace several strings, error message for FA_errno

  • November 26, 2025
  • 1 reply
  • 200 views

Hi,

I had to search and replace more than 60 long numbers with other numbers. Would take time, error-prone.

Therefore I wrote a short ExtendScript script to do this.

I found a start here:

https://community.adobe.com/t5/framemaker-discussions/find-replace/m-p/3581679

(Russ Ward and Ian Prowdfood, thank you very much!)

(I just put the search and replace strings into an array and did not copy them from elsewhere. Easier with the help of Notepad++.)

However, I always get an error message that FA_errno would be read only.

I found another info here:

https://community.adobe.com/t5/framemaker-discussions/are-there-situations-where-you-can-not-override-the-fa-errno-s-code/m-p/3897361

Therefore I replaced the call to FA_errno with the function.

But why do I get this error message, when others obviously do not have any issues?

Best regards, Winfried

---

#target framemaker
"use strict";
#strict on

(function () {

var loDoc, loFlow, lsFindString, lsReplaceString, lsConsiderCase, lsReplacementCounter;
var laStrings = [];
var laStringSearchReplace = [];

loDoc = app.ActiveDoc;
if (!loDoc.ObjectValid ()) {
    Alert ("Document required ", Constants.FF_ALERT_CONTINUE_NOTE);
    return;
}
loFlow = loDoc.MainFlowInDoc;
CreateStringsArray (laStrings);

//$.writeln ("laStrings.length: " + laStrings.length);
//$.writeln ("laStrings [0]: " + laStrings [0]);

for (var li = 0; li < laStrings.length ; li += 1) 
{
    lsFindString = laStrings [li][0];
    lsReplaceString = laStrings [li][1];
    lsConsiderCase = 1;
    lsReplacementCounter = FindAndReplaceString (loDoc, loFlow, lsFindString, lsReplaceString, lsConsiderCase)
    $.writeln ("lsReplacementCounter: " + lsReplaceString + "   " + lsReplacementCounter);
}
$.writeln ("Done");



function FindAndReplaceString (foDoc, foFlow, fsFindString, fsReplaceString, fsConsiderCase) {
// From Adobe forum:
// https://community.adobe.com/t5/framemaker-discussions/find-replace/m-p/3581679

    var tr = new TextRange();
    var restoreTR, frame = 0;
    var loopCounter = 0, replacementCounter = 0;
    var findParams = new PropVals();

    //  if the flow object is not valid, assume the main flow
    if (foDoc.ObjectValid() && !foFlow.ObjectValid()) {
        foFlow = foDoc.MainFlowInDoc;
    }

    // get the first text frame in the flow, a starting point to
    // find the first paragraph
    if (foFlow.ObjectValid()) {
        frame = foFlow.FirstTextFrameInFlow;
    }

    // At this point, if we don't have a frame object, might as well abort.
    if (!frame.ObjectValid()) {
        Alert ("Could not find a starting point for the search. Cannot continue." , Constants.FF_ALERT_CONTINUE_WARN);
        return replacementCounter;
    }

    // store the original text selection as an amenity to restore after the action.
    restoreTR = foDoc.TextSelection;

    // now, set up the starting text range as the very beginning
    // of the flow. We'll move straight from beginning to end.
    tr.beg.obj = tr.end.obj = frame.FirstPgf;
    tr.beg.offset = tr.end.offset = 0;

    // set up our find parameters. We want to configure it to look
    // for a string and perhaps be case sensitive. We don't need
    // the find to wrap because we are controlling the flow from
    // beginning to end.
    findParams = AllocatePropVals (2);

    findParams [0].propIdent.num = Constants.FS_FindText;
    findParams [0].propVal.valType = Constants.FT_String;
    findParams [0].propVal.sval = fsFindString;

    findParams [1].propIdent.num = Constants.FS_FindCustomizationFlags;
    findParams [1].propVal.valType = Constants.FT_Integer;
    if (fsConsiderCase) {
        findParams [1].propVal.ival = Constants.FF_FIND_CONSIDER_CASE;
    }
    else {
        findParams [1].propVal.ival = 0;
    }

    // initialize the errno global, which will be used to
    // track the progress of the find and replace
    initFA_errno ();
    //FA_errno = Constants.FE_Success;

    // and do an initial find to get started.
    tr = foDoc.Find (tr.beg, findParams);

    // now, run the find and replace loop as long as we keep finding things.
    // The loop counter is just an emergency back door in case something
    // goes critically wrong and causes an endless loop.
    while (FA_errno === Constants.FE_Success && loopCounter++ < 1000) {

        // set up the text range to clear the original text
        foDoc.TextSelection = tr;

        // clear it
        foDoc.Clear (0);

        // insert the new text. We should be able to use the
        // original beginning of the text range where the old text was
        // found.
        foDoc.AddText (tr.beg, fsReplaceString);

        // now, lets jimmy the text range in memory to place it directly
        // after the string we just inserted, so the find picks back up after that.
        tr.beg.offset += fsReplaceString.length;

        // increment our return counter
        if (FA_errno === Constants.FE_Success) {
            replacementCounter++;
        }

        // ...and find the next instance. We'll reset FA_errno again just in case
        // something screwy happened while we were replacing text.
        initFA_errno ();
        //FA_errno = Constants.FE_Success;
        tr = foDoc.Find (tr.beg, findParams);
    }

    // we're done. Restore the document to it's original area of display
    foDoc.TextSelection = restoreTR;
    foDoc.ScrollToText (restoreTR);

    return replacementCounter;
} // --- end FindAndReplaceString


function CreateStringsArray (laStrings) {
    laStringSearchReplace = ["12345", "67890"];
    laStrings.push (laStringSearchReplace);
} // --- end CreateStringsArray


function initFA_errno () {
    app.GetNamedMenu("!MakerMainMenu"); //If this fails, you've got bigger problems
    return;
}

})(); //--- end

 

1 reply

frameexpert
Community Expert
Community Expert
November 26, 2025

I wouldn't use FA_errno here if it's giving you problems. I would simply use:

while (tr.beg.obj.ObjectValid () === 1) {

 

www.frameexpert.com
Community Expert
November 26, 2025

Thank you very much! Works equally well.

Still I would like to know, why some people can use FA_errno, and I run the same code and get error messages.

frameexpert
Community Expert
Community Expert
November 26, 2025

I am not really sure. It may be broken in ExtendScript.

www.frameexpert.com