Highlighted

How to Insert a Framemaker Variable Using Extendscript

New Here ,
Jun 29, 2017

Copy link to clipboard

Copied

I've been fighting with this for several days and just cannot get the results I need.

The situation: I work in technical/how-to documentation. Several older documents use a font-face to represent mouse and keyboard actions. Since it's a font, it's not accessible. In an effort to make accessible documentation, we are trying to convert the font characters to text variables. The text variables exist in the document, so it's simply a matter of finding the characters to be replaced and replacing them with the appropriate variable. Some of our documents are over 100 pages, so replacing the characters manually would be frustrating.

Current State of Solution: I have created a script that looks through a document, then inserts the text value of the variable in the text, but for some reason, I can't figure out how to make it insert the variable object itself. I've taken scripts from around these forums and modified them to work in my situation, so here are the functions that I'm working with:

Find and Replace function

function FindAndReplaceEdufont(docum, flow, findString, replaceVarName) {

    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(docum.ObjectValid() && !flow.ObjectValid()){

        flow = docum.MainFlowInDoc;

    }

    //get the first text frame in the flow, a starting point to

    //find the first paragraph

    if(flow.ObjectValid()){

        frame = flow.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 = docum.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 = findString;

   

    findParams[1].propIdent.num = Constants.FS_FindCustomizationFlags;

    findParams[1].propVal.valType = Constants.FT_Integer;

    findParams[1].propVal.ival = 0;

   

    //initialize the errno global, which will be used to

    //track the progress of the find and replace

    FA_errno = Constants.FE_Success;

   

    //and do an initial find to get started.

    tr = docum.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

        docum.TextSelection = tr;

        //clear it

        docum.Clear(0);

        // insert the variable at the found

        addVariable(docum, tr, 0, Constants.FO_Var, replaceVarName);

      

        /* Old code that replaced found text with text

        //insert the new text. We should be able to use the

        //original beginning of the text range where the old text was

        //found.

        docum.AddText(tr.beg, replaceVarName);

        ////// This is where I should create the variable.

        //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 += replaceVarName.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.

        FA_errno = Constants.FE_Success;

        tr = docum.Find(tr.beg, findParams);

    }

    //we're done. Restore the document to it's original area of display

    docum.TextSelection = restoreTR;

    docum.ScrollToText(restoreTR);

    return replacementCounter;

}

Add Variable function:

function addVariable(doc, tr, offset, type, format) {

    // Use Create Variable function like this: createVariable(doc, pgf, 0, Constants.FO_Var, "Current Date (Long)", "Index");

    var tl, textVar;

    tl = new TextLoc(tr, offset);

    //Get the variable object by name

    textVar = GetNamedVarFmt(format);

   

    //Insert into variable

    doc.addText(variable, tl);

   

    //Return something because... #whynot?

    return 1;

    //textVar = doc.NewAnchoredFormattedObject(type, format, tl);

    //textVar = doc.NewAnchoredFormattedVar(format, tl);

    

}

The characters to be replaced are in an array like this:

var find_me = [["char-to-find","var-name-for-replace"],["char-to-find","var-name-for-replace"]];

The function is called via a loop that sends "char-to-find" and "var-name-for-replace" to FindAndReplaceEdufont like this:

// Setup Document Variables

var currentDocument = app.ActiveDoc;

var mainTextFlow = app.ActiveDoc.MainFlowInDoc;

// Find all old edufont characters and replace them with the variables

for (i = 0; i < find_me.length; i+=1) {

    FindAndReplaceEdufont(currentDocument,  mainTextFlow, find_me[0], find_me[1]);

}

Like I mentioned, it currently replaces the character with the text inside the variable, not with an instance of the variable itself. I've tried using NewAnchoredFormattedObject() and NewAnchoredFormattedVar() and they both had the same results (commented out in the above code).

So... what am I doing wrong? I can't seem to crack this nut at all...

Any help would be very much appreciated!

tm

Adobe Community Professional
Correct answer by frameexpert | Adobe Community Professional

To insert a variable, you need to use the NewAnchoredFormattedVar method of the Doc object. Here is a way to add a variable at the insertion point. You should be able to modify this to work in your script.

#target framemaker

var doc = app.ActiveDoc;

// Get the paragraph object where the cursor is.

var pgf = doc.TextSelection.beg.obj;

// Make a text loc object.

var textLoc = new TextLoc (pgf, 0);

// Make sure the variable format exists.

var varFmt = doc.GetNamedVarFmt ("MyVariable");

if (varFmt.ObjectValid () === 1) {

    // Add the variable at the text location.

    doc.NewAnchoredFormattedVar ("MyVariable", textLoc);

}

TOPICS
Scripting

Views

732

Likes

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

How to Insert a Framemaker Variable Using Extendscript

New Here ,
Jun 29, 2017

Copy link to clipboard

Copied

I've been fighting with this for several days and just cannot get the results I need.

The situation: I work in technical/how-to documentation. Several older documents use a font-face to represent mouse and keyboard actions. Since it's a font, it's not accessible. In an effort to make accessible documentation, we are trying to convert the font characters to text variables. The text variables exist in the document, so it's simply a matter of finding the characters to be replaced and replacing them with the appropriate variable. Some of our documents are over 100 pages, so replacing the characters manually would be frustrating.

Current State of Solution: I have created a script that looks through a document, then inserts the text value of the variable in the text, but for some reason, I can't figure out how to make it insert the variable object itself. I've taken scripts from around these forums and modified them to work in my situation, so here are the functions that I'm working with:

Find and Replace function

function FindAndReplaceEdufont(docum, flow, findString, replaceVarName) {

    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(docum.ObjectValid() && !flow.ObjectValid()){

        flow = docum.MainFlowInDoc;

    }

    //get the first text frame in the flow, a starting point to

    //find the first paragraph

    if(flow.ObjectValid()){

        frame = flow.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 = docum.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 = findString;

   

    findParams[1].propIdent.num = Constants.FS_FindCustomizationFlags;

    findParams[1].propVal.valType = Constants.FT_Integer;

    findParams[1].propVal.ival = 0;

   

    //initialize the errno global, which will be used to

    //track the progress of the find and replace

    FA_errno = Constants.FE_Success;

   

    //and do an initial find to get started.

    tr = docum.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

        docum.TextSelection = tr;

        //clear it

        docum.Clear(0);

        // insert the variable at the found

        addVariable(docum, tr, 0, Constants.FO_Var, replaceVarName);

      

        /* Old code that replaced found text with text

        //insert the new text. We should be able to use the

        //original beginning of the text range where the old text was

        //found.

        docum.AddText(tr.beg, replaceVarName);

        ////// This is where I should create the variable.

        //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 += replaceVarName.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.

        FA_errno = Constants.FE_Success;

        tr = docum.Find(tr.beg, findParams);

    }

    //we're done. Restore the document to it's original area of display

    docum.TextSelection = restoreTR;

    docum.ScrollToText(restoreTR);

    return replacementCounter;

}

Add Variable function:

function addVariable(doc, tr, offset, type, format) {

    // Use Create Variable function like this: createVariable(doc, pgf, 0, Constants.FO_Var, "Current Date (Long)", "Index");

    var tl, textVar;

    tl = new TextLoc(tr, offset);

    //Get the variable object by name

    textVar = GetNamedVarFmt(format);

   

    //Insert into variable

    doc.addText(variable, tl);

   

    //Return something because... #whynot?

    return 1;

    //textVar = doc.NewAnchoredFormattedObject(type, format, tl);

    //textVar = doc.NewAnchoredFormattedVar(format, tl);

    

}

The characters to be replaced are in an array like this:

var find_me = [["char-to-find","var-name-for-replace"],["char-to-find","var-name-for-replace"]];

The function is called via a loop that sends "char-to-find" and "var-name-for-replace" to FindAndReplaceEdufont like this:

// Setup Document Variables

var currentDocument = app.ActiveDoc;

var mainTextFlow = app.ActiveDoc.MainFlowInDoc;

// Find all old edufont characters and replace them with the variables

for (i = 0; i < find_me.length; i+=1) {

    FindAndReplaceEdufont(currentDocument,  mainTextFlow, find_me[0], find_me[1]);

}

Like I mentioned, it currently replaces the character with the text inside the variable, not with an instance of the variable itself. I've tried using NewAnchoredFormattedObject() and NewAnchoredFormattedVar() and they both had the same results (commented out in the above code).

So... what am I doing wrong? I can't seem to crack this nut at all...

Any help would be very much appreciated!

tm

Adobe Community Professional
Correct answer by frameexpert | Adobe Community Professional

To insert a variable, you need to use the NewAnchoredFormattedVar method of the Doc object. Here is a way to add a variable at the insertion point. You should be able to modify this to work in your script.

#target framemaker

var doc = app.ActiveDoc;

// Get the paragraph object where the cursor is.

var pgf = doc.TextSelection.beg.obj;

// Make a text loc object.

var textLoc = new TextLoc (pgf, 0);

// Make sure the variable format exists.

var varFmt = doc.GetNamedVarFmt ("MyVariable");

if (varFmt.ObjectValid () === 1) {

    // Add the variable at the text location.

    doc.NewAnchoredFormattedVar ("MyVariable", textLoc);

}

TOPICS
Scripting

Views

733

Likes

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
Jun 29, 2017 0
Adobe Community Professional ,
Jun 29, 2017

Copy link to clipboard

Copied

To insert a variable, you need to use the NewAnchoredFormattedVar method of the Doc object. Here is a way to add a variable at the insertion point. You should be able to modify this to work in your script.

#target framemaker

var doc = app.ActiveDoc;

// Get the paragraph object where the cursor is.

var pgf = doc.TextSelection.beg.obj;

// Make a text loc object.

var textLoc = new TextLoc (pgf, 0);

// Make sure the variable format exists.

var varFmt = doc.GetNamedVarFmt ("MyVariable");

if (varFmt.ObjectValid () === 1) {

    // Add the variable at the text location.

    doc.NewAnchoredFormattedVar ("MyVariable", textLoc);

}

Likes

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
Reply
Loading...
Jun 29, 2017 0
_tlmason LATEST
New Here ,
Jun 30, 2017

Copy link to clipboard

Copied

That's great! I finally got it working. Now to get the paragraph offset from a text selection!

Likes

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
Reply
Loading...
Jun 30, 2017 0