11 Replies Latest reply on Dec 22, 2016 4:28 AM by Loic.Aigon

    Code to be evaluated! [012]  Extract the Table Title! …

    Obi-wan Kenobi Adobe Community Professional

      Hi Scripters,

       

      Table Titles are included in the first row of each table and I want to "extract" them before the table using a para style "Title" applied to them!

       

      Before:

       

      Capture d’écran 2016-12-21 à 23.54.55.png

       

      After:

       

      Capture d’écran 2016-12-21 à 23.55.22.png

       

      I've written the code below. Even if it totally works well, I'm not sure [as usual!] it's the more beautiful code we can read!

       

      Thanks for your comments! 

       

      app.doScript("main()", ScriptLanguage.javascript, undefined, UndoModes.ENTIRE_SCRIPT, "Extract Title! …");
      
      
      function main()     
      {
      
      
          var  
          myDoc = app.activeDocument,    
          myTables = myDoc.stories.everyItem().tables.everyItem().getElements();    
          
          for ( var T = 0 ; T < myTables.length; T++ )    
              {    
                  myTables[T].storyOffset.paragraphs[0].duplicate(LocationOptions.after, myTables[T].storyOffset.paragraphs[0]);
                  var myRows = myTables[T].rows;
                  var R = myRows.length;
                  while ( R -- )  if (R != 0)  myRows[R].remove();
                  var myTitle = myTables[T].convertToText("\t", "\r");
                  myTitle.appliedParagraphStyle = "Title";
              }
          
          myTables = myDoc.stories.everyItem().tables.everyItem().getElements();
          var T = myTables.length;
          while ( T-- )  myTables[T].rows[0].remove();
          
      }
      

       

       

      (^/)

        • 1. Re: Code to be evaluated! [012]  Extract the Table Title! …
          Laubender Adobe Community Professional & MVP

          Hi Obi-wan,

          if you are sure that every table in your document has a title and you want to move it out of the table why don't you move just the text of cell one to an insertion point?

           

          Example:

           

          /*
              Preconditions:
              1. There are tables in the document
              2. All cells in the first row are merged to one cell
              3. The first row contains text
              4. The last character of that text is no paragraph sign
              5. There is a paragraph style named "Title"
          */
          
          var doc = app.documents[0];
          var tables = doc.stories.everyItem().tables.everyItem().getElements();
          
          for(var n=tables.length-1;n>=0;n--)
          {
              var index = tables[n].storyOffset.index;
              var story = tables[n].storyOffset.parentStory;
             
              tables[n].cells[0].insertionPoints[-1].contents = "\r";
              tables[n].cells[0].texts[0].move(LocationOptions.AT_BEGINNING , story.insertionPoints[index]);
              tables[n].rows[0].remove();
             
              story.insertionPoints[index].paragraphs[0].appliedParagraphStyle = "Title";
          }
          

           

          Regards,
          Uwe

          • 2. Re: Code to be evaluated! [012]  Extract the Table Title! …
            Vamitul Level 4

            Uwe was faster.
            Also, Obi, try your code on a document that has no tables!

            • 3. Re: Code to be evaluated! [012]  Extract the Table Title! …
              Loic.Aigon Adobe Community Professional

              Obi,

               

              Think I already advised you this but this simple line will save you efforts and energy:

               

              if ( !app.documents.length) return;

              myDoc = app.activeDocument

               

              or you will have execution error at the very first moment your code will be run.

               

              Also, in a loop, don't look at the length property but reference it before

              var n = tables.length;

              for ( i=0; i<n; i++ )…

               

              If you want to acquire good practices.

              • 4. Re: Code to be evaluated! [012]  Extract the Table Title! …
                Obi-wan Kenobi Adobe Community Professional

                Uwe, Vlad and Loic,

                 

                Thanks for your interest! …

                 

                Uwe's code is obviously more interesting and more relevant (and more written too! )! Thanks for it!

                 

                I'm going to insert "if" statements in it to take in account these 2 points:

                 

                1/ if open doc and if no table.

                2/ if the contents of the first row (merger or not [1-column table) is a table title (para style applied) - a necessary filter!

                Imho, no need to verify if "Title" para style exists and if the last is not a para sign! It seems logical for me even if not always for users!

                 

                Do I need to use a try … catch for the first point?

                 

                (^/)

                • 5. Re: Code to be evaluated! [012]  Extract the Table Title! …
                  Obi-wan Kenobi Adobe Community Professional

                  Hi Loic,

                   

                  About the second point, why is it a better practice? …

                   

                  (^/)

                  • 6. Re: Code to be evaluated! [012]  Extract the Table Title! …
                    Loic.Aigon Adobe Community Professional

                    Because the script engine won't reach a property of an object (the length property of the array ) every loop. It will only read a value stored in memory. It might not be obvious for a small loop but with huge loops the difference can be sensitive.

                     

                    Besides why would you want to force convert the collection into an array with

                    1. var tables = doc.stories.everyItem().tables.everyItem().getElements(); 

                    A collection is an array like object so it does have a length property too and you can loop through the same way. Once again, unless you want to sue some specific arrays methods, it's useless to to so.

                     

                    FWIW

                     

                    Loic

                    • 7. Re: Code to be evaluated! [012]  Extract the Table Title! …
                      Vamitul Level 4

                      About Loic's second point:

                      The theory is that you are caching the array's length so instead of accessing the length property each step in the loop you only access it once, thus speeding up the script.

                      However, that's the theory, in practice I never noticed any difference and I assume the ExtendScript engine does do some optimisations to the loops.

                      So I just use the for (var i=0; i<arr.length; i++) format.

                      Loic.Aigon, do you have some data to show that it does make any difference?

                      • 8. Re: Code to be evaluated! [012]  Extract the Table Title! …
                        Vamitul Level 4

                        About converting collections to arrays:

                        It actually makes a lot of difference and it can significantly speed up the script.

                        Iterating through a collection will make a request to the DOM for each member of the collection, in order to resolve the specifier.

                        Using the everyItem().getElements() to convert to an array will only touch the DOM once, and return an array of actual honest indesign objects, not specifiers, which results in a huge speed increase.

                        To illustrate, use the following code:

                        (function(){
                         var d=app.documents.add();
                         for (var i=0; i<100; i++){
                          d.pages.add();
                         }
                         $.hiresTimer;
                         var p=d.pages;
                         for (var i=0; i<p.length;i++){
                          $.write(p[i].name);
                         }
                         $.writeln('\r'+$.hiresTimer);
                         var p=d.pages.everyItem().getElements();
                         for (var i=0; i<p.length;i++){
                          $.write(p[i].name);
                         }
                         $.writeln('\r'+$.hiresTimer);
                        }());
                        
                        • 9. Re: Code to be evaluated! [012]  Extract the Table Title! …
                          Loic.Aigon Adobe Community Professional

                          var a  = new Array(10000);

                           

                           

                          var t = (new Date() ).getTime();

                          var i = 0;

                          var n = a.length;

                          for ( i = 0; i<a.length; i++ ) {

                            a[i] = new Date();

                          }

                          (new Date() ).getTime()-t;

                           

                          > ~120

                           

                          var a  = new Array(10000);

                           

                           

                          var t = (new Date() ).getTime();

                          var i = 0;

                          var n = a.length;

                          for ( i = 0; i<n; i++ ) {

                            a[i] = new Date();

                          }

                          (new Date() ).getTime()-t;

                           

                          > ~75

                           

                           

                          • 10. Re: Code to be evaluated! [012]  Extract the Table Title! …
                            Obi-wan Kenobi Adobe Community Professional

                            … So, a double good practice is to:

                             

                            • convert a collection to an array, using "everyItem().getElements()"

                            • define ~.length as a variable before using it n a loop

                             

                            Right?

                             

                            (^/)

                            • 11. Re: Code to be evaluated! [012]  Extract the Table Title! …
                              Loic.Aigon Adobe Community Professional

                              Vamitul

                              It actually makes a lot of difference and it can significantly speed up the script.

                              That's a good one and I will certainly make mine from now on

                               

                              Happy holidays !

                               

                              Loic