13 Replies Latest reply on Jun 8, 2012 1:40 AM by [Jongware]

    Adding rows bug ? CS4 JS

    TᴀW Adobe Community Professional & MVP

      Try this:

       

      Create a doc with a text frame. Add a table: 2 columns, 3 rows. Select

      the entire table.

       

      Now run this script.

       

      It should add 5 rows. But it adds about 20. Why?

       

      myTable = app.selection[0];

      myRow = myTable.rows[1];

      for (a=0; a<4; a++){

           myTable.rows.add(LocationOptions.AFTER, myRow);

      }

       

        • 1. Re: Adding rows bug ? CS4 JS
          [Jongware] Most Valuable Participant

          Yup, found that out myself not long ago. *No idea* at all what goes wrong -- it really seems the entire table gets added again.

           

          By way of workaround I used this, which strangely *does* work:

           

          new_row = row.parent.rows.add(LocationOptions.AFTER, row.cells[0]);
          
          • 2. Re: Adding rows bug ? CS4 JS
            TᴀW Adobe Community Professional & MVP

            Excellent (haven't tested it yet though)! I used (LocationOptions.AFTER,

            myTable.rows[myRow.index]) which is clearly more irritating.

             

            I'll probably rewrite the script when I get round to it, with your idea.

            (Interesting script by the way -- it splits a table row into as many

            rows as there are text lines in that row, and then copies the text lines

            carefully into the newly created rows. What for? Workaround to get table

            cells to split at a page turn. )

             

            I think the bug actually adds double the number of rows you've been

            adding. So first time -- 1. Then 12, 124, 1248, etc.

             

            Initially it looked like the reference to myRow was getting broken

            (which would happen I guess if you were adding rows BEFORE my row). But

            in this case we're adding the rows after it, so there's no reason it

            shouldn't stay valid.

             

            Ariel

            • 3. Re: Adding rows bug ? CS4 JS
              [Jongware] Most Valuable Participant

              > (Interesting script by the way -- it splits a table row into as many

              rows as there are text lines in that row, and then copies the text lines

              carefully into the newly created rows.

               

              's Funny -- that particular line came from *my* version of exactly such a script.

               

              I got it working for "simple" cases but I had to abandon developing it further cause of just so many hours-per-day. I hope you run onto the same problems I did ... and then can find the time to solve them!

              • 4. Re: Adding rows bug ? CS4 JS
                Marc Autret Level 4

                This only sounds like a bug...

                 

                In your original code, keep in mind that the myRow variable is a specifier that becomes out-of-sync after each myTable.rows.add(LocationOptions.AFTER, myRow). It is a typical example where you need to resolve again a specifier as the parent object is evolving. (There are a number of similar issues with Text specifiers BTW.)

                 

                The simplest way to force a new resolution of a specifier is getElements()—you don't even need to use the returned value, just call the method!

                So the following patch should work (I hope!):

                 

                myTable = app.selection[0];

                myRow = myTable.rows[1];

                 

                for (a=0; a<4; a++){

                     myTable.rows.add(LocationOptions.AFTER, myRow);

                 

                     // Need to re-resolve myRow!

                     myRow.getElements();

                }

                 

                 

                Anyway, cells objects are weird.

                 

                @+

                Marc

                • 5. Re: Adding rows bug ? CS4 JS
                  TᴀW Adobe Community Professional & MVP

                  Hi Marc,

                   

                  Yup,  that works!

                   

                  Believe it or not, I was aware of the issue of specifiers getting

                  unresolved etc.

                   

                  I just didn't think it would happen in this case because I was adding

                  rows AFTER the row X -- so I thought that row X would stay valid.

                   

                  Thanks,

                  Ariel

                  • 6. Re: Adding rows bug ? CS4 JS
                    TᴀW Adobe Community Professional & MVP

                    Jongware,

                     

                    That is a funny coincidence.

                     

                    My script is very tailor-made: it only works with 2-column tables, where

                    one of the columns is English (or any LTR lang.) and the other Hebrew.

                    Basically for a book with many passages of side-by-side translations...

                     

                    Ariel

                    • 7. Re: Adding rows bug ? CS4 JS
                      [Jongware] Most Valuable Participant

                      So myRow might be going out of sync because the table is rebuilt "from scratch" -- I'd buy that, IF it suddenly got invalidated somewhere. It keeps on working instead.

                       

                      But where do these magically doubled-and-doubled-again rows come from? I had a HECK of a time going through the motions one step at a time, only to find that after *every loop iteration* adding a single row suddenly seemed to mean "nah you get TWO rows", then FOUR, then ...

                      • 8. Re: Adding rows bug ? CS4 JS
                        Marc Autret Level 4

                        Hi Jongware,

                         

                        Please, don't ask me how this internally degenerates ;-) All I can say is that the speficier becomes unresolved, which does not exactly mean not valid. I suppose that the inner indices still point out to something. Apparently after the first pass myRow addresses two rows or something, then myTable.rows.add(LocationOptions.AFTER, myRow) behaves as if there were two rows to augment, and so on. Maybe myRow is then seen as a plural specifier—a kind of everyItem()—I don't know… The fact is just that myRow is no more what you think it is for the reason I tried to explain. Therefore the specifier must be updated to get the loop working as expected.

                         

                        @+

                        Marc

                        • 9. Re: Adding rows bug ? CS4 JS
                          Marc Autret Level 4

                          Here is a funny way to support my theory:

                           

                          myTable = app.selection[0];

                          myRow = myTable.rows[1];

                           

                          for (a=0; a < 4; a++)

                          {

                              myTable.rows.add(LocationOptions.AFTER, myRow);

                              // myRow.getElements();

                           

                              myRow.contents = 'A single row, really?';

                          }

                           

                          @+

                          Marc

                          • 10. Re: Adding rows bug ? CS4 JS
                            TᴀW Adobe Community Professional & MVP

                            What's still counterintuitive to me is that myRow.getElements() works. I

                            would have thought that if myRow is "broken" (dereferenced? whatever you

                            want to call it) it could be risky to rely on getElements() to fix it.

                             

                            Ariel

                            • 11. Re: Adding rows bug ? CS4 JS
                              Marc Autret Level 4

                              The secret is that myRow is not a row! It's nothing but a path in the object hierarchy (a specifier).

                              We may see myRow as a basic structure that simply stores an address, such as:

                               

                              "/document[@id=1]//text-frame[2]/table[5]/row[1]"

                               

                              The actual path depends on the way the variable is defined. In your case, the main part of the path is already resolved when you send the very first command to the specifier because the subsystem needs to access the textframe and the table (which are persistent components). So, probably myRow looks more like this:

                               

                              "/document[@id=1]//text-frame[@id=217]/table[@id=228]/row[1]"

                               

                              Well. This path seems quite stable at first sight. But you already know that rows are not persistent components (they have no ID.) Under the hood, tables only contain cell ranges. Rows are pure abstractions as well as words, lines, or paragraphs regarding text streams. Indeed, myTable.rows[1] is very similar to myStory.words[1]: the range or indices these specifiers point out to highly depend on the current state of the parent object (table or story).

                               

                              Now, the first time you send a command to myRow (i.e., the first time you use myRow in your script), the specifier is internally resolved—if valid. In other words, a specific location (range, indices, pointers, whatever) is determined within the target table and attached to myRow. This is a subsystem thing. You cannot 'unresolve' myRow in itself, but of course you could simply affect to myRow a new unresolved specifier—myRow = myTable.rows[1]—and then wait for the right time to send a new command!

                               

                              Meanwhile, something is happening to myTable: myTable.rows.add(LocationOptions.AFTER, myRow);

                               

                              One might assume that this has no effect on the inner location attached to myRow, due to LocationOptions.AFTER, but since we have no idea of how the cells are actually handled and managed by the subsystem, this is a weak assumption! Note that it's easy to get similar issues with text ranges:

                               

                              var myChar = myStory.characters[1];

                              myChar.duplicate(LocationOptions.AFTER, myChar);

                              alert( myChar.contents ); // => 2 characters!!!

                               

                              To conclude, the inner location attached to myRow is no more what we perceive as myTable.row[1]. From now, if you still need to access to myTable.row[1], then:

                               

                              (a) Use explicitly myTable.row[1] (by nature, this forces a resolution)

                               

                              OR

                               

                              (b) Find a way to re-resolve myRow.

                              …which is just the purpose of the getElements() method (“Resolves the object specifier,” etc.)

                               

                              What makes getElements() more reliable than other methods is that it actually updates the specifier from its original path, so it remembers that myRow is (was) defined as myTable.row[1], in fact: "/document[@id=1]//text-frame[@id=217]/table[@id=228]/row[1]"

                               

                              That's why myRow.getElements() resets myRow to what it really means and solves your problem.

                               

                              @+

                              Marc

                              • 12. Re: Adding rows bug ? CS4 JS
                                Harbs. Level 6

                                Very nice Marc.

                                 

                                You have a real knack for explaining complex concepts in understandable terms. Well done.

                                • 13. Re: Adding rows bug ? CS4 JS
                                  [Jongware] Most Valuable Participant

                                  Marc Autret wrote:

                                   

                                  Under the hood, tables only contain cell ranges. Rows are pure abstractions as well as words, lines, or paragraphs regarding text streams. Indeed, myTable.rows[1] is very similar to myStory.words[1]: the range or indices these specifiers point out to highly depend on the current state of the parent object (table or story).

                                   

                                  That sentence alone made me go "oooo-h-h". I'm familiar with surprising side effects when dealing with 'words' and 'lines', so I always have this mental "these are not real" shield in place. From now on I'll raise the shields for tables as well.

                                   

                                  Well done indeed!