6 Replies Latest reply on Aug 30, 2012 9:18 AM by Marc Autret

    Transferring "contents", using everyitem()

    Laubender Adobe Community Professional & MVP

      Hello, everyone!

       

      I want to use a fast method of transferring contents from one cell of a table to another cell of the same table.

       

      And that for every table in a story.

       

      A simplyfied example:

      Goal: Move the contents of the first cell of the last column of every table to the first cell of the first column of the table.

       

      All tables have DIFFERENT columnCount values.

       

       

      I thought of using the everyItem() method Marc Autret is explaining here:

       

      http://www.indiscripts.com/post/2010/06/on-everyitem-part-1

      http://www.indiscripts.com/post/2010/07/on-everyitem-part-2

       

      //EDIT:

      With the contents-property of a cell it's working very well.*

      It's a two-step process.

      1. Assign the new contents

      2. Remove the old contents

       

      //EDIT: * Sorry, that is NOT working at all. The contents of the first entry of the Array everyItem() is building is transferred to ALL THE tables. This is not what I like to do. Conclusion: only a loop through all the tables will work…

       

       

      See the following working snippet:

       

      var everyTableInStory = app.documents[0].pages[0].textFrames[0].parentStory.tables.everyItem();
      
      //Assign new contents:
      try{
      everyTableInStory.columns[0].cells[0].contents = everyTableInStory.columns[-1].cells[0].contents;
      catch(e){$.writeln(e.message)};
      
      //Remove old contents:
      everyTableInStory.columns[-1].cells[0].contents = "";
      

       

      But how to tranfer formatted text with a similar method?

      Unfortunately:

       

      var everyTableInStory = app.documents[0].pages[0].textFrames[0].parentStory.tables.everyItem();
      everyTableInStory.columns[-1].cells[0].texts[0];
      

      returns just ONE SINGLE texts object for multiple tables.

       

       

      So the following thing will NOT work. It fails SILENTLY:

       

      var everyTableInStory = app.documents[0].pages[0].textFrames[0].parentStory.tables.everyItem();
      try{
      everyTableInStory.columns[0].cells[0].texts[0] = everyTableInStory.columns[-1].cells[0].texts[0];
      catch(e){$.writeln(e.message)};
      

       

      We could resolve the single returned texts object by adding getElements(), but that will not work in the following example. It also fails SILENTLY:

       

      var everyTableInStory = app.documents[0].pages[0].textFrames[0].parentStory.tables.everyItem();
      try{
      everyTableInStory.columns[0].cells[0].texts[0] = everyTableInStory.columns[-1].cells[0].texts[0].getElements();
      catch(e){$.writeln(e.message)};
      

       

      Another try, but I assumed in advance, that it will fail, because the built Array of the first getElements() method seems to have no connection to the real existing tables in the story:

      (ERROR: Value cannot be assigned)

       

      var everyTableInStory = app.documents[0].pages[0].textFrames[0].parentStory.tables.everyItem();
      try{
      everyTableInStory.columns[0].cells[0].texts[0].getElements() = everyTableInStory.columns[-1].cells[0].texts[0].getElements();
      catch(e){$.writeln(e.message)};
      

       

      And that leads to my main question:

      Is there a workaround for the problem?

       

      I think, we can rule out the move() and duplicate() methods, because they take only ONE SINGLE object as argument for the target.

       

      I checked both, the move() method and the duplicate() method, in the following way:

      (ERROR: Invalid value for parameter "reference" of method "move" …)

       

      var everyTableInStory = app.documents[0].pages[0].textFrames[0].parentStory.tables.everyItem();
      try{
      everyTableInStory.columns[-1].cells[0].texts[0].move(LocationOptions.AT_BEGINNING,everyTableInStory.columns[0].cells[0]);
      }catch(e){$.writeln(e.message)};
      

       

      I'll be happy for every comment and recommendation :-)

       

      Uwe

        • 1. Re: Transferring "contents", using everyitem()
          Laubender Adobe Community Professional & MVP

          To all, I made a big mistake in using the first snippet. It's not working at all. Other than I stated in the unedited version of the first post.
          If you do that, ALL TABLES will get the same contents in the first cell of the first column.

           

          Uwe

          • 2. Re: Transferring "contents", using everyitem()
            Marc Autret Level 4

            Hi Uwe,

             

            You can't use a collective specifier—xxx.everyItem()—as the target of a move(). More generally, collective specifiers must be involved in N-to-1 commands, such as xxx.everyItem().fillColor = /*singular Color*/ or xxx.everyItem().duplicate(…, /*singular Destination*/). You can't implement N-to-N commands by that approach. Also, note that there is no way to specify a bijective relationship between two collective specifiers. When you write sth like:

             

            xxx.everyItem().selectorA.move(…, xxx.everyItem().selectorB);

             

            you wrongly assume that there could be a kind of implicit N-to-N connection between the receivers of xxx.everyItem().selectorA and the receivers of xxx.everyItem().selectorB, while they simply are, well, two collective specifiers.

             

            Whatever the source specifier, mySourceSpecifier.move(…, collectiveSpecifier) can't work because a unique, single destination is required.

             

            Anyway, you could make your moving method compliant with a collective specifier as shown below:

             

            Table.prototype.myCustomMoveCells = function()
            //--------------------------------------
            {
                var LO_BEG = LocationOptions.AT_BEGINNING;
            
                var a = this.getElements(),
                    i = a.length,
                    t;
                
                while( i-- )
                    {
                    t = a[i].columns;
                    t[-1].cells[0].texts[0].
                        move(LO_BEG, t[0].cells[0].texts[0].insertionPoints[0]);
                    }
            
                a.length = 0;
                a = t = null;
            };
            
            // Sample code
            // ---
            var story = app.activeDocument.stories[0];
            story.tables.everyItem().myCustomMoveCells();
            

             

            Hope that helps.

             

            @+

            Marc

            • 3. Re: Transferring "contents", using everyitem()
              Laubender Adobe Community Professional & MVP

              More generally, collective specifiers must be involved in N-to-1 commands

               

              Hi, Marc!

              I found out that truth in my more empiric experiments.

               

              I will try out your prototype function and will report back, if it will run faster on my tables than the usual for loop through the tables.

               

              Thank you very much for shedding some more light to the "Collective Specifiers" thing…

               

              Uwe

              • 4. Re: Transferring "contents", using everyitem()
                Trevorׅ Adobe Community Professional

                Hi Marc

                 

                Brillant peice of code.

                 

                Now, WAY WAY WAY off the topic

                I had a grep problem over here http://forums.adobe.com/message/4652870#4652870

                As I know you are a bit of a greper I thought you might know the answer.

                 

                Please bear in mind that the question is more of a challenge than a need so don't waist too much time on it!

                 

                Regards

                 

                Trevor

                 

                @ Uwe

                 

                Sorry about the "highjack" please also look at the above link.

                • 5. Re: Transferring "contents", using everyitem()
                  Laubender Adobe Community Professional & MVP

                  Hi, Marc!

                   

                  The function is working very well! Thank you again.

                   

                  Just a question about your prototype function:

                   

                  a.length = 0;
                  a = t = null;
                  
                  

                   

                  Is that a "necessity", a "must" when using "protoytype" to extend an object?

                  Or is it just because of cleaning up behind and trying to lower memory consumption?

                   

                  Uwe

                  • 6. Re: Transferring "contents", using everyitem()
                    Marc Autret Level 4

                    Laubender wrote:

                     

                    […]
                    Is that a "necessity", a "must" when using "protoytype" to extend an object?

                    Or is it just because of cleaning up behind and trying to lower memory consumption?

                     

                    Just my bad habit of cleaning up object references ;-)

                    According to my colleagues, absolutely unnecessary.

                     

                    @+

                    Marc