Framemaker 12 and Framemaker 15 get stuck after one complete traversal of all Paragraphs in the doc
Copy link to clipboard
Copied
Hi,
I noticed that after one traversal of all paragraphs as given by function 1, framemaker gets stuck and maybe due to that I am unable to execute the while loop in the second function. ($.writeln("CHECK2"); doesn;t get executed)
Please let me know if I am missing out on closing some dangling variables etc. I have attached the code as well.
Thanks,
Sebin
var doc = app.ActiveDoc;
doc.ShowCondIndicators =1;
var txtFile = "C:/gen_seb.txt";
var file = new File(txtFile);
file.open("w"); // open file with write access
var hash = generate_list(doc);
find_defined_list_attributes(doc);
file.close();
function generate_list(doc)
{
var list = {};
var pgf= doc.FirstPgfInDoc;
var cndfmt = doc.FirstCondFmtInDoc;
var count = 0 ;
//doc.CondFmtIsShown = 1;
doc.ShowAll = 0;
while (pgf.ObjectValid()){
var test = pgf.GetText(Constants.FTI_String);
var text, str;
text = "";
for (var i=0; i < test.len ; i +=1)
{
var str=test .sdata.replace(/^\s+|\s+$/g, '') ;
text = text + str;
}
if (pgf.Name == 'Name_1')
{
var tr = new TextRange ();
tr.beg.obj = tr.end.obj = pgf;
tr.beg.offset = 0;
tr.end.offset = Constants.FV_OBJ_END_OFFSET;
var props = doc.GetTextPropVal(tr.beg,Constants.FP_InCond);
if(props.propVal.isval.length >0)
{
var cnt = 0;
var con_shown = 0;
var propLength= props.propVal.isval.length;
while(cnt<propLength)
{
if((props.propVal.osval[cnt].CondFmtIsShown))
{
con_shown = 1;
break;
}
else
cnt++;
}
if(con_shown == 1)
{
file.writeln(text);
var regexp = /\(\S+\)/gi;
var regmatch = text.match(regexp);
regmatch=String(regmatch);
regmatch= regmatch.replace(/\(|\)/g, '');
list[regmatch] = [0,0];
}
}
}
pgf=pgf.NextPgfInDoc;
}
return reg_list;
}
function find_defined_list_attributes(doc)
{ $.writeln("CHECK1");
var pgf= doc.FirstPgfInDoc;
while (pgf.ObjectValid())
{ $.writeln("CHECK2");
pgf=pgf.NextPgfInDoc;
}
}
Copy link to clipboard
Copied
Hi,
I reduced the contents of the mif file and ran the same. I was able to execute the above code without framemaker crashing.
Since it is a memory issue, could you please let me know how I could deallocate memory for my text items. I tried using DeallocateTextItems() from the manual but it didn't work.(function is not defined).
Any help in tackling the memory issue would be deeply appreciated.
Thanks,
Sebin
Copy link to clipboard
Copied
sebinkur,
I don't see any immediate reason why the script would hang, but I see several things that seem suspicious and/or could use improvement.
1 - I don't know what this is:
var list = {};
I'm not the foremost expert in javascript, but that notation doesn't look like anything to me. If you were trying to declare an array, I would expect var list = new Array(). And besides, it doesn't look like this variable is used anywhere anyway.
2 - generate_list() returns reg_list which is not declared anywhere.
3 - generate_list() retrieves the text for every paragraph, whether it is used or not. This is an expensive process. I would move the text retrieval into the if(con_shown ==1) conditional.
4 - To retrieve text properties, you don't need a whole text range, only a text location. For example (note, did not test this);
var tl = new TextLoc ();
tl.obj = pgf;
tl.offset = 0;
var props = doc.GetTextPropVal(tl,Constants.FP_InCond);
5 - Overall, the code structure is inefficient, with too many nested conditionals. But this should not cause the problem you are seeing. It just makes the code harder to read and maintain.
6 - You should not need to deallocate any data structures. JavaScript should use automatic trash collection. If it does not, there is a bug. While bugs have been encountered, your code doesn't look extensive enough to exhaust memory even if there were a bug.
I hope this helps some.
Russ
Copy link to clipboard
Copied
Russ,
var list = {}; Is normal JavaScript. It's an Object literal and an efficient notation for creating a new empty object. Once it's declared you can add or remove name/value pairs easily.
You can do the same for arrays too like this: var myArray = [];
Ian
Copy link to clipboard
Copied
Thanks Ian. I did not know that. So then Ian or Sebin, what does this line do?
list[regmatch] = [0,0]
Copy link to clipboard
Copied
Hi Ian,
There were some typos when I copied the code here as far as variables are concerned.
list and reg_list are the same.
var list = {}; This is a hash that holds a specific text from each paragraph as a key. Its value is an array that can hold 2 attributes (Attribute_1 and Attribute_2). In the first function, my goal is to grab all item names from the paragraph with tag (Name_1) and check if the associated conditional text is not hidden from the document. Once I have a hash of all the items, my goal is to iterate through all paragraphs (in the second function with Paragraph tag Name_2). Then check if the following paragraphs until the next new line have Attribute_1 and Attribute_2 defined. If not define Attribute_1 and 2 as a variable in a proceeding new paragraph with a conditional text applied to it.
My Code is currently directed at updating Attribute_1 only.
As I had told you earlier, I had reduced the size of the mif file almost into half by deleting stuff and surprisingly my code works for that small mif file.
I have attached the code that runs successfully for smaller mif files. One of the reasons to follow two different iterations was the way that document is laid out.
//Create List of all Registers in the File #include "FunctionLibrary.jsx" var doc = app.ActiveDoc; doc.ShowCondIndicators =1; var txtFile = "C:/Users/skuriako/Documents/Framemaker/Junk/gen_seb.txt"; var file = new File(txtFile); file.open("w"); // open file with write access var itemhash = generate_itemlist(doc); find_defined_item_attributes(doc, itemhash); $.summary(); file.close(); function generate_itemlist(doc) { var item_list = {}; var pgf= doc.FirstPgfInDoc; var cndfmt = doc.FirstCondFmtInDoc; var count = 0 ; //doc.CondFmtIsShown = 1; //doc.ShowAll = 0; while (pgf.ObjectValid()){ if (pgf.Name == 'Name_1') { var tr = new TextRange (); tr.beg.obj = tr.end.obj = pgf; tr.beg.offset = 0; tr.end.offset = Constants.FV_OBJ_END_OFFSET; var props = doc.GetTextPropVal(tr.beg,Constants.FP_InCond); if(props.propVal.isval.length >0) { var cnt = 0; var con_shown = 0; var propLength= props.propVal.isval.length; while(cnt<propLength) { if((props.propVal.osval[cnt].CondFmtIsShown)) { con_shown = 1; break; } else cnt++; } if(con_shown == 1) { var test = pgf.GetText(Constants.FTI_String); var text, str; text = ""; for (var i=0; i < test.len ; i +=1) { var str=test .sdata.replace(/^\s+|\s+$/g, '') ; text = text + str; } test = null; //file.writeln(text); var regexp = /\(\S+\)/gi; var itemmatch = text.match(regexp); itemmatch=String(itemmatch); itemmatch= itemmatch.replace(/\(|\)/g, ''); //item_list.push(itemmatch); item_list[itemmatch] = 0; } props = null; } tr = null; //app.DeallocateTextItems(test); } pgf=pgf.NextPgfInDoc; } return item_list; } function find_defined_item_attributes(doc, itemhash) { //$.writeln("CHECK1"); var pgf= doc.FirstPgfInDoc; var para_found = 0; var item_found; while (pgf.ObjectValid()) { //file.writeln("CHECK2"); if (pgf.Name == 'Name_2') { count += 1; var test = pgf.GetText(Constants.FTI_String); var text, str; text = ""; //$.writeln(test); for (var i=0; i < test.len ; i +=1) { var str=test .sdata.replace(/^\s+|\s+$/g, '') ; //var str=test .sdata; text = text + str; //PrintTextItem (test + 'END'); } if(text in itemhash)//&& para_found != 1) { para_found = 1; item_found = text; $.writeln("In Hash: ", text); } if(para_found == 1 && text.match(/Attribute_1/g)) { itemhash[item_found] =1; $.writeln("Attribute already Available: ", item_found); } else if((para_found == 1) && (text =="") && (itemhash[item_found] ==0)) { //$.writeln("SEB"); //Update Attribute_1 as a Variable var newpgf = doc.NewSeriesObject(Constants.FO_Pgf, pgf); //var newpgf = doc.TextSelection.beg.obj; var textLoc = new TextLoc(); textLoc.obj = newpgf; textLoc.offset = -1; textLoc = doc.AddText (textLoc, "("); doc.NewAnchoredFormattedVar ("Variable_x", textLoc); textLoc = new TextLoc (newpgf, Constants.FV_OBJ_END_OFFSET - 2); textLoc = doc.AddText (textLoc, ")"); //Set Conditional Tag to Variable_x var tr = doc.TextSelection ; var newFmt = doc.GetNamedCondFmt("Condition_X"); var props = doc.GetTextPropVal(tr.beg,Constants.FP_InCond); props.propVal.isval[0] = newFmt.id; props.propVal.osval[0] = newFmt; //$.writeln(props.propVal.osval[0]); tr = new TextRange (); tr.beg.obj = tr.end.obj = pgf; tr.beg.offset = 0; tr.end.offset = Constants.FV_OBJ_END_OFFSET; FA_errno = Constants.FE_Success; doc.SetTextPropVal(tr, props); if (FA_errno != Constants.FE_Success){ $.writeln ("Error : " + FA_errno); } para_found = 0; } }// Name_2 pgf=pgf.NextPgfInDoc; } //~ var array_keys = new Array(); //~ var array_values = new Array(); //~ for (var key in itemhash) { //~ array_keys.push(key); //~ array_values.push(itemhash[key]); //~ } //~ $.writeln(array_keys); //~ $.writeln(array_values); }
Thanks,
Sebin
Copy link to clipboard
Copied
I can see three things that looks suspicious, but I am only guessing at the goal of the script in the first place.
1. You set Doc.ShowAll to false before starting to process the paragraphs. AFAIK, paragraphs that have a condition applied to them which is currently hidden do not show up as paragraphs at all, so you will miss those in the script.
2. You use a shorthand to assign the same paragraph to two objects: tr.beg.obj = tr.end.obj = pgf;
The scripting wrapper often just copies a pointer and not the entire object. This might cause unexpected results. Better make sure by splitting these two assignments up. Not sure if it makes a difference here, though.
3. You are processing all paragraphs in the document. This includes paragraphs on master and reference pages. My guess is you want to process the paragraphs in the main flow. Start with initializing pfg to Doc.MainFlowInDoc.FirstTextFrameInFlow.FirstPgf and then walk through the doc using pgf.NextPgfInFlow.
Of course you might get more useful comments when you tell us in words what exactly you want to do with your script. It is hard for me to tell what the logic really is.
Copy link to clipboard
Copied
Hello all,
I think I have narrowed down the problem. For my mif file, I understood that once I iterate through every paragraph (25000 paragraphs in my current mif ) in the document, Framemaker hangs.
If I limit the size of the mif file substantially or limit the while loop like this: while (pgf.ObjectValid() && count <12000). I can see that Framemaker doesn't hang and I can run the script multiple times over the same document.
I am very new to Framemaker, so it would be great if you could suggest a possible solution to this scenario. FYI, the code that I attached in the previous reply works fine with a smaller mif file.
==================================
var doc = app.ActiveDoc;
var txtFile = "C:/Users/skuriako/Documents/Framemaker/Junk/dump.txt";
var file = new File(txtFile);
var flag1;
file.open("w");
generate_reglist(doc);
file.close();
function generate_reglist(doc){
var pgf = doc.FirstPgfInDoc;
var count = 0 ;
while (pgf.ObjectValid() ){
count += 1 ;
pgf=pgf.NextPgfInDoc;
}
$.writeln(count);
}
Copy link to clipboard
Copied
Hi sebinkur,
I guess that it is caused by "$.writeln".
$.writeln is slowing down a script while debugging very much. Also there are known problems with it.
e.g. $.writeln(anynumber) isn't written, but with some text in it : $.writeln("No. :" + anynumber) it is written
I suggest that you try to test it with something like this:
count += 1 ;
count1000 +=1
if (count1000 == 1000)
{
$.writeln("Count: " + count);
count1000 = 0;
}
Copy link to clipboard
Copied
Hi Klaus,
I wrote something like what you suggested, but it didn't work for me. The script can only be executed once after which Framemaker is stalled until I force close it.
-Sebin
var doc = app.ActiveDoc;
var pgf = doc.FirstPgfInDoc;
var count = 0 ;
var count1000 = 0;
while (pgf.ObjectValid() ){
count += 1 ;
count1000 +=1 ;
pgf=pgf.NextPgfInDoc;
if (count1000 == 1000)
{
$.writeln("Count: " + count);
count1000 = 0;
}
}
Copy link to clipboard
Copied
Hi Sebin,
if you want, you can send me this document, so I can investigate?
You can find my website in my profile. emaiL: development@.....
That problem makes me very curious.
Copy link to clipboard
Copied
Hi Sebin,
after several tests I can reconstruct this error. I try to narrow it down and then I will report it as a bug to the developers.
Copy link to clipboard
Copied
Hi Sebin,
what did you want to achieve with your script?
Esp. with find_defined_list_attributes?
I can imagine, that there's another way doing this. Perhaps as a workaround and to avoid this crash you yould use mif instead.
Copy link to clipboard
Copied
Hi Sebin,
thanks to Stefan Gentz https://forums.adobe.com/people/Stefan%20Gentz%20%5BAdobe%5D and the development-team this issue will be solved in update 2.
They worked on it today (Sunday!!) to solve the problem.
MANY THANKS TO THEM ALL.
Copy link to clipboard
Copied
Hello Klaus,
Thank you so much for the help.
Could you let me know how I could get the "update 2" ? I am currently using Framemaker 12.
Thanks,
Sebin
Copy link to clipboard
Copied
Hello Klaus,
Please let me know how could I update my current framemaker version to accommodate the "update 2"?
Thanks,
Sebin
Copy link to clipboard
Copied
We have just released Update 1 for FrameMaker 2017. There is no Update 2 yet.
Copy link to clipboard
Copied
We have investigated this further, and this bug is in ExtendScript and not FrameMaker.
The Script is crashing when a number of objects exceeds around 50,000 due to the garbage collection process of ExtendScript.
As soon as I have an update from the ExtendScript team, I will let you know.

