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

ES: Opening the 5th book component from the end

Participant ,
Oct 25, 2015 Oct 25, 2015

Copy link to clipboard

Copied

Hello fellows,

I wonder what is the best way to find the 5th book component from the end of the book (so the 1st book component to count is basically the last one). 

I can loop through all components and get a list of all of them. Then, I guess, I need to somehow put them into an array and find the 5th one from the bottom?

Any ideas will be appreciated!

TOPICS
Scripting

Views

560

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

Community Expert , Oct 26, 2015 Oct 26, 2015

unshift is an array method that puts an item into the front of the array instead of the back. So if you had an array of numbers:

var array = [1, 2, 3, 4, 5];

and did this:

array.unshift (6);

you would have this:

[6, 1, 2, 3, 4, 5]

Normally, you use push to put items on an array:

array.push (6);

would give you:

[1, 2, 3, 4, 5, 6]

Votes

Translate

Translate
Contributor ,
Oct 26, 2015 Oct 26, 2015

Copy link to clipboard

Copied

I cannot see any alternative to iterating through all the book components, storing the component ids as you go..

I'd use a buffer big enough to hold only 5 component ids. Store each successive component id you find in location (counter modulo 5) - so it's effectively a circular buffer. When you reach the last component in the book, the component you want will be the next entry in the circular buffer. This method saves memory, and handles a book of any size.

Whether or not you use the above method, ensure you gracefully handle a book with fewer than 5 components. In the above case, I'd intiialize the buffer to nulls, and check for a non-null value at the end.

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
Mentor ,
Oct 26, 2015 Oct 26, 2015

Copy link to clipboard

Copied

Mike, Rom, all this sounds good so far, but why bother with buffers at all? I would just go to the end with FP_NextComponentInBook, then step backwards 5 times with FP_PrevComponentInBook. Given the speed of this type of operation, I don't think that you would see any performance issues even with a very large book.

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
Participant ,
Oct 26, 2015 Oct 26, 2015

Copy link to clipboard

Copied

Hi Russ,

I wonder why there is no LastComponentInBook. It would be easier to start counting from it.

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
Participant ,
Oct 26, 2015 Oct 26, 2015

Copy link to clipboard

Copied

Hi Mike,

Thank you for your response!

How would you create and manage this buffer?

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
Community Expert ,
Oct 26, 2015 Oct 26, 2015

Copy link to clipboard

Copied

This is how I would do it:

#target framemaker

var comps = [];

var book = app.ActiveBook;

var bookComp = book.FirstComponentInBook;

while (bookComp.ObjectValid ()) {

    // put the components into the array in reverse order.

    comps.unshift (bookComp);

    bookComp = bookComp.NextBookComponentInDFSOrder;

}

alert (comps[4].Name);

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
Participant ,
Oct 26, 2015 Oct 26, 2015

Copy link to clipboard

Copied

Hi Rick,

Thank you for your response and for the suggested code! What does the unshift method do? I couldn't find it in the scripting guide.


Thank you!

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
Community Expert ,
Oct 26, 2015 Oct 26, 2015

Copy link to clipboard

Copied

unshift is an array method that puts an item into the front of the array instead of the back. So if you had an array of numbers:

var array = [1, 2, 3, 4, 5];

and did this:

array.unshift (6);

you would have this:

[6, 1, 2, 3, 4, 5]

Normally, you use push to put items on an array:

array.push (6);

would give you:

[1, 2, 3, 4, 5, 6]

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
Participant ,
Oct 26, 2015 Oct 26, 2015

Copy link to clipboard

Copied

Hi Rick,

Thank you for the explanations!

Now I see that unshift is a standard JS method. I need to learn more about arrays.

Thank you for your help!

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
Participant ,
Oct 27, 2015 Oct 27, 2015

Copy link to clipboard

Copied

Hello fellows,

Let's say I have a book open and also a standalone FM file that is not part of that book.

I previously opened this standalone FM file as follows:

var openFM = Open(dname, openParams, openReturnParams), where dname is the full name of that FM file, openFileParams and openFileReturnParams are defined in a function that lists all relevant open params.


var openParams = getOpenPrefs();

var openReturnParams =  new PropVals();

function getOpenPrefs() {

    var params, i;

    params = GetOpenDefaultParams();

    i = GetPropIndex(params, Constants.FS_RefFileNotFound);

    params.propVal.ival = Constants.FV_AllowAllRefFilesUnFindable;  

    i = GetPropIndex(params, Constants.FS_FileIsOldVersion);

    params.propVal.ival = Constants.FV_DoOK;

    i = GetPropIndex(params, Constants.FS_FontChangedMetric);

    params.propVal.ival = Constants.FV_DoOK;

    i = GetPropIndex(params, Constants.FS_FontNotFoundInCatalog);

    params.propVal.ival = Constants.FV_DoOK;

    i = GetPropIndex(params, Constants.FS_FontNotFoundInDoc);

    params.propVal.ival = Constants.FV_DoOK;

    i = GetPropIndex(params, Constants.FS_LockCantBeReset);

    params.propVal.ival = Constants.FV_DoOK;  

    i = GetPropIndex(params, Constants.FS_FileIsInUse);

    params.propVal.ival = Constants.FV_OpenViewOnly;

    return (params);

}

After getting the 5th book component, I open it as follows:

var T_FM = comps[4].Name;

var openT_FMParams = getOpenPrefs();

var openT_FMReturnParams =  new PropVals();

var openT_FM = Open(T_FM, openT_FMParams , openT_FMReturnParams ).

So now, I have 2 FM files open in addition to the book. The active FM file is the 5th book component that I just opened.

Now, I'd like to import formats from the 5th book component to the standalone FM file (dname) and then close the 5th book component.

I tried doing that as follows:

openFM.SimpleImportFormats(openT_FM, Constants.FF_UFF_COND|Constants.FF_UFF_FONT|Constants.FF_UFF_PAGE |Constants.FF_UFF_PGF|Constants.FF_UFF_REFPAGE|Constants.FF_UFF_TABLE|Constants.FF_UFF_VAR|Constants.FF_UFF_XREF);

                      

openT_FM.Close(Constants.FF_CLOSE_MODIFIED, true);

This part does not work for a reason that is unclear to me. What could be the cause of this problem?

Thank you for your input in advance!

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
Community Expert ,
Oct 27, 2015 Oct 27, 2015

Copy link to clipboard

Copied

After the Open method, you should confirm that the template did open correctly.

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

    // opened correctly.

}

Also, there is a special constant for importing all formats:

openFM.SimpleImportFormats(openT_FM, Constants.FF_ALL);

As far as closing the template without saving changes, all you need is this:

openT_FM.Close(true);

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
Participant ,
Oct 28, 2015 Oct 28, 2015

Copy link to clipboard

Copied

Hi Rick,

Thank you for your response. It works only if all the operations described above are defined within the same function. But what if I'd like to split that into 2 functions?

How, for example, do I pass the openFM variable defined and opened in Function A to Function B that will open openT_FM and import the formats to openFM? How do I make local function var's visible to other functions?

Thank you for your explanations in advance!

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
Participant ,
Oct 28, 2015 Oct 28, 2015

Copy link to clipboard

Copied

Hi Rick,

Let's say I would like not to count excluded book components that appear at the end of the book. So I tried changing the while statement as follows:

  1. ...
  2. while (bookComp.ObjectValid () & bookComp.ExcludeBookComponent !==1) { 
  3.     // put the components into the array in reverse order. 
  4.     comps.unshift (bookComp); 
  5.     bookComp = bookComp.NextBookComponentInDFSOrder; 
  6.  
  7. alert (comps[4].Name);


However, in this case, the  comps[4] element is one of the first components of the book. Any idea why comps[4] is now counted from the top?


Thank you!

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
Community Expert ,
Oct 28, 2015 Oct 28, 2015

Copy link to clipboard

Copied

Try using && on line 2.

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
Participant ,
Oct 28, 2015 Oct 28, 2015

Copy link to clipboard

Copied

LATEST

Hi Rick,

I appreciate your response.


I tried that previously. As a result, comps[4] is an LOT file (which is the fourth component from the top of the book ).

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