14 Replies Latest reply on Oct 28, 2015 8:20 AM by rombanks

    ES: Opening the 5th book component from the end

    rombanks Level 1

      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!

        • 1. Re: ES: Opening the 5th book component from the end
          Mike-Hardy Level 3

          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.

          • 2. Re: ES: Opening the 5th book component from the end
            Russ Ward Level 4

            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

            • 3. Re: ES: Opening the 5th book component from the end
              rombanks Level 1

              Hi Mike,

               

              Thank you for your response!

              How would you create and manage this buffer?

              • 4. Re: ES: Opening the 5th book component from the end
                frameexpert Level 4

                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);
                
                • 5. Re: ES: Opening the 5th book component from the end
                  rombanks Level 1

                  Hi Russ,

                   

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

                  • 6. Re: ES: Opening the 5th book component from the end
                    rombanks Level 1

                    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!

                    • 7. Re: ES: Opening the 5th book component from the end
                      frameexpert Level 4

                      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]

                      • 8. Re: ES: Opening the 5th book component from the end
                        rombanks Level 1

                        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!

                        • 9. Re: ES: Opening the 5th book component from the end
                          rombanks Level 1

                          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[i].propVal.ival = Constants.FV_AllowAllRefFilesUnFindable;  

                              i = GetPropIndex(params, Constants.FS_FileIsOldVersion);

                              params[i].propVal.ival = Constants.FV_DoOK;

                              i = GetPropIndex(params, Constants.FS_FontChangedMetric);

                              params[i].propVal.ival = Constants.FV_DoOK;

                              i = GetPropIndex(params, Constants.FS_FontNotFoundInCatalog);

                              params[i].propVal.ival = Constants.FV_DoOK;

                              i = GetPropIndex(params, Constants.FS_FontNotFoundInDoc);

                              params[i].propVal.ival = Constants.FV_DoOK;

                              i = GetPropIndex(params, Constants.FS_LockCantBeReset);

                              params[i].propVal.ival = Constants.FV_DoOK;  

                              i = GetPropIndex(params, Constants.FS_FileIsInUse);

                              params[i].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_VA R|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!

                          • 10. Re: ES: Opening the 5th book component from the end
                            frameexpert Level 4

                            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);
                            
                            • 11. Re: ES: Opening the 5th book component from the end
                              rombanks Level 1

                              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!

                              • 12. Re: ES: Opening the 5th book component from the end
                                rombanks Level 1

                                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!

                                • 13. Re: ES: Opening the 5th book component from the end
                                  frameexpert Level 4

                                  Try using && on line 2.

                                  • 14. Re: ES: Opening the 5th book component from the end
                                    rombanks Level 1

                                    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 ).