• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

NewElementInHierarchy() - Adding New Elements, progressively takes longer when adding multiple siblings

Explorer ,
Aug 20, 2014 Aug 20, 2014

Copy link to clipboard

Copied

With my ESTK script, users select model numbers from a list and then the script inserts an element with a model number entered into an attribute, one element for each model selected.

When adding a large number of elements, each additional sibling element takes a little longer to add then the previous element. Adding 250 elements can take upwards of 3-1/2 minutes or more. While adding 20, 50, or 75 elements happens quickly, without any noticeable duration. It’s somewhere above 110 is where it starts to be noticeable.

I even used $.hiresTimer and wrote the value to the console for each time a model was added. Since the timer is reset back to zero (0) each time it's called, it was easier to notice that the amount it incremented from one element to the next got progressively larger.

Any thoughts as to why it’s taking so long or thoughts on what I could do to speed it up?

The structure looks like this:

<PartModels>
      <NoteText>Text</NoteText>
      <Model ModelNumber=”ABC01”/>
      <Model ModelNumber=”ABC02”/>
      <Model ModelNumber=”DEF03”/>
      <Model ModelNumber=”DEF04”/>
      …
      …
      <Model ModelNumber=”XYZ01-A”/>
      <Model ModelNumber=”XYZ*B”/>
      <Model ModelNumber=”XYZ500”/>
</PartModels>

The script is somewhat straight forward: cycle through an array of the model numbers selected, add a new element for each model number and set it's attribute value to the model number. This is the short version:

Function InsertModelElements (modelsToIns, insElemLoc, GVdoc) {

     var newEleId;

     var newElemLoc = insElemLoc;

     var elemDef = GVdoc.GetNamedElementDef(“Model”);

     for(var i = 0; i < modelsToIns.length; i++){ // modelsToIns is the array of models selected

          newEleId = elemDef.NewElementInHierarchy(newElemLoc); //ElementLoc based on NoteText first, last, or not present

          SetAttribute(newEleId, "ModelNumber", null, modelsToIns); //more robust function to set attribute

         

          /*Which also works for setting attribute*/

          //var vattributes = newEleId.GetAttributes();

          //vattributes[0].values[0] = modelsToIns;

          //newEleId.Attributes = vattributes;


          /*At one point I tried using a new element location from the last inserted element, no change*/

          //var newElemRange = setElementSelection(GV_doc, EleId); //function that returns range

          //newElemLoc = newNewElemRange.end;

                }

}

Any help is appreciated.

Sincerely,

Trent

TOPICS
Scripting

Views

428

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
community guidelines

correct answers 1 Correct answer

Explorer , Aug 25, 2014 Aug 25, 2014

Thanks Russ,

I seriously considered trying copy/paste and started to modify the code to do so. But I couldn't let it go, the answer had to be right there in front of me, just it's been too long since I've worked with this stuff, I'm not able to see it. Then it dawned on me what is happening.

In an earlier test, I placed a timer on each action that is looped through. For example, I start with an container element that has 200 children elements, each with a specific/unique model number attribute. Al

...

Votes

Translate

Translate
Community Expert ,
Aug 20, 2014 Aug 20, 2014

Copy link to clipboard

Copied

Hi Trent,

You could try turning off "Validating" and see if that speeds things up.

app.Validating = 0;

When the script is done, turn it back on:

app.Validating = 1;

Rick

Votes

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
community guidelines
Explorer ,
Aug 20, 2014 Aug 20, 2014

Copy link to clipboard

Copied

Thanks Rick,

I'm actually doing that, along with temporarily turning off notifications (Pre/Post InsertElement, ChangeElement, SetAttrValue, etc.), and app.Displaying, Reformating, AutoSave, AutoBackup. All those together reduce the total time about a second or two on inserting something like 250 elements, no difference on smaller numbers.

It seems as if FrameMaker is doing something, automatically, but I don't what that is. (I don't even know how to describe it.) When the element is inserted at the end, it's like FrameMaker goes through the compelte node, starting with the first element (first child of the parent), all the way to the last element just inserted. I tried reversing how elements are inserted, inserting new elements at the beginning instead of at the end and get the same results.

For S&G's, I added Console("Delete " + $.hiresTimer); to the part of the function that deletes the previous elements before the new elements are inserted. The first element deleted takes the longest and progressively takes less and less time as each element is deleted.

Any other thoughts are appreciated.

Sincerely,

Trent

Votes

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
community guidelines
Explorer ,
Aug 21, 2014 Aug 21, 2014

Copy link to clipboard

Copied

Update-

If I turn off ApplyFormatRules (app.ApplyFormatRules = 0;) before inserting the elements (then turning it back on at the end), it takes under a second to delete the previous elements and add all 250+ new elements.

The element being inserted is defined as "General rule: <EMPTY>" and "Text format - rules In all contexts. - Text range.", the element doesn't take up space or adds new paragraph. But since ApplyFormatRules is off when the elements are inserted, each element is inserted in a new paragraph. So now I get 250 empty paragraphs. Turning ApplyFormatRules back on, turning on app.Reformatting, and then doc.Reformat() doesn't change anything.

If I manually select just one of the inserted elements or their parent, select the Element Def in the Catalog and click Change, the new inserted elements are then reformatted properly and the paragraphs go away. So, I save the last inserted element object reference and added the following at the end of the function right before I turn back on the Displaying, Reformating, and Notifications:

     app.ApplyFormatRules = 1;

     LastInsElemRef.ElementDef = GVdoc.GetNamedElementDef(myElemDefName);

Which works and all happens within a second or so. Still, I'm curious if there is a better way, or at least a more definitive explanation of why or what is happening. Any thoughts?

Sincerely,

Trent Schwartz

Votes

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
community guidelines
Explorer ,
Aug 25, 2014 Aug 25, 2014

Copy link to clipboard

Copied

Hi Trent,

I've seen this behavior ever since I started with the FDK over a decade ago. I never figured out why the operations progressively took longer.

My recommendation is to use copy/paste, rather than the insertion of a new object every time. That is, insert one, stick it on the clipboard, then paste the rest. It seems to work much better for me.

Russ

Votes

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
community guidelines
Explorer ,
Aug 25, 2014 Aug 25, 2014

Copy link to clipboard

Copied

LATEST

Thanks Russ,

I seriously considered trying copy/paste and started to modify the code to do so. But I couldn't let it go, the answer had to be right there in front of me, just it's been too long since I've worked with this stuff, I'm not able to see it. Then it dawned on me what is happening.

In an earlier test, I placed a timer on each action that is looped through. For example, I start with an container element that has 200 children elements, each with a specific/unique model number attribute. All 200 existing elements are deleted and then replaced with 250 new elements with a different value for the model number attribute. The timer was placed after the Element.Delete() method and ElementDef.NewElementInHierarchy() method. What I noticed with the timer is that each element deleted was deleted faster than the previous element (so it progressively took less and less time to delete an element). And of course the opposite was noticed for inserting elements, each element inserted took longer than the previous element inserted.

These elements can be inserted in two areas of the structure, one of the areas has fewer format rules that impact the formatting and is actually a little quicker. This led me to the cause being the EDD format rules. The area that takes longer has quite a few extensive format rules that apply. Every time an element is inserted or deleted, FrameMaker runs through those rules to format the content of the elements. Since the rules apply to parent, first, last, next, previous, etc., FrameMaker has to apply format rules to all the elements in the structure that the rules apply to (which are extremely complex because of the various elements, attribute values, and combinations that can be inserted).

Removing or thinning down the FormatRules in the EDD, it does get quicker. But each of the FormatRules are needed. So using app.ApplyFormatRules = false; right before the elements are deleted and inserted works great. But the key is to set ApplyFormatRules back to true before deleting the last element to be deleted and before inserting the last element to be inserted, so it will cycle through all the format rules of the EDD for all the elements in the hierarchy those format rules apply to. Setting ApplyFormatRules to true and assigning the ElementDef to the last element also works [EleId.ElementDef = GV_doc.GetNamedElementDef(insElemType);], but only before any other functions are performed or different elements are added.

doc.Reformat() isn't going to reformat the content correctly after the fact because the element was created without the format rules, so it just reformats the content of the elements without the format rules.

The FDK version that was created 10 years ago had the same problem of running slow when a large number of elements were being inserted, but was still an improvement over having to manually insert each element and type in the attribute value, so it was lived with.

It's now working amazingly fast. I hope my explanation of what I think is happening, including the cause/solution, is understandable.

Sincerely,

Trent Schwartz

Votes

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
community guidelines