Hi All.
I have never used FrameMaker until today so this is my first post here. :-)
I have combined a file-reading script and Ian Proudfoot's Search and Replace script into a script that reads comma separated values from a file, and then searches the FrameMaker file for the first string in the array and if found replaces that string with the second string in the array. Making it possible to e.g. loop through a list of old product numbers and replacing them with new ones.
It does actually work, but the thing is that the people who are going to use this script are still using FrameMaker 9.So I need to convert this script to a FDK script. And i need to inform them how to run this script in FrameMaker 9.
So does anyone know if there are any easy ways of converting this ExtendScript to a FDK script to be used in FM9. And could anyone please help me understand how such a script would be run in FrameMaker 9?
Here's "my" script:
//initializing variables
var activeDoc = app.ActiveDoc;
var flow = activeDoc.MainFlowInDoc;
var findString = '';
var replaceString = '';
var considerCase = 0;
// telling FrameMaker which file to open
var csvFile = File.openDialog('Select a CSV File','comma-separated-values(*.csv):*.csv;');
if (csvFile != null)
{
sarArray = readInCSV(csvFile); //read the file into the Search And Replace (sar) array using the readInCSV function
}
for (var i=0, len=sarArray.length; i < len; i++) { //loop through the array and do a search and replace for each collection of elements in the array
findString = sarArray[i][0]; //the find string is the first element in the current collection
replaceString = sarArray[i][1] //the replace string is the second element in the current collection
FindAndReplaceString(activeDoc, flow, findString, replaceString, considerCase) //the actual search and replace routine
}
function readInCSV(fileObj)
{
var sarArray = new Array(); //creating the array
fileObj.open('r'); //open the file for reading
fileObj.seek(0, 0); //go to the beginning of the file
while(!fileObj.eof) //as long as end of file has not been reached
{
var thisLine = fileObj.readln(); //read each line
var csvArray = thisLine.split(';'); //split the line in two at the ; character
sarArray.push(csvArray); //insert each value into the array
}
fileObj.close(); //close the file
return sarArray; //and return an array full of search and replace strings
}
function FindAndReplaceString(activeDoc, flow, findString, replaceString, considerCase) {
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(activeDoc.ObjectValid() && !flow.ObjectValid()){
flow = activeDoc.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 = activeDoc.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;
if(considerCase){
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
FA_errno = Constants.FE_Success;
//and do an initial find to get started.
tr = activeDoc.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++ < 1500){
//set up the text range to clear the original text
activeDoc.TextSelection = tr;
//clear it
activeDoc.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.
activeDoc.AddText(tr.beg, replaceString);
//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 += replaceString.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 = activeDoc.Find(tr.beg, findParams);
}
//we're done. Restore the document to it's original area of display
activeDoc.TextSelection = restoreTR;
activeDoc.ScrollToText(restoreTR);
return replacementCounter;
}