7 Replies Latest reply on Feb 17, 2009 5:48 PM by (Dave_Saunders)

    [JS CS3] Merging table columns

    Level 1
      Hi all,

      What's the fastest way to merge columns in a table?

      I'm using the following loop to merge the 4th and 5th columns in my table:
      for( var f = myTable.rows.length-1; f >= 0; f-- ){
      myTable.columns[3].cells[f].merge (myTable.columns[4].cells[f])
      }

      It works, but I'm working on a large table (120 pages worth) and have many instance where I need to merge columns. Using the loop above, the script takes hours to run. Is there a faster way to merge columns while keeping the rows intact?

      Thanks,
      Michael
        • 1. Re: [JS CS3] Merging table columns
          Peter Kahrel Adobe Community Professional & MVP
          Michael,

          You can optimise two things in your code. First, avoid referring to collections (such as myTable.rows and myTable.columns) repeatedly. Instead, create arrays from collections. Earlier this week this was discussed here: Harbs, "[JS] :: [CSX] - PageItem Stacking Order" #15, 6 Jan 2009 11:23 am . see especially the reference to Kris Coppetier's article in Harbs's post, who explains that each time you refer to a collection, InDesign rebuilds it -- so you can imagine that rebuilding a big table such as yours causes the script to run for hours.

          In your case, instead of referring to myTable.rows.length-1, do this:

          myRows = myTable.rows.everyItem().getElements();
          myRows_length = myRows.length-1;
          for (var f = myRows; . . .

          Secondly, you needn't refer to myRows[f].columns[...].cells[...]: myRows[...].cells[...] will do too. So your script coulkd look like this:
          myRows = myTable.rows.everyItem().getElements();
          
          myRows_length = myRows.length-1;
          for (var f = myRows_length; f >= 0; f--)
             myRows[f].cells[3].merge (myRows[f].cells[4]);

          This will probably speed things up.

          Peter
          • 2. Re: [JS CS3] Merging table columns
            Level 1
            I did some timing experiments a while back on referencing cells in tables and I was amazed to discover that the fastest way to reference a cell is:

            myTable.cells.item("c:r")

            where c is the column number and r is the row number. This was significantly faster (in my tests, probably in early CS3 days but might have been earlier) than any other method I could think of.

            Dave
            • 3. Re: [JS CS3] Merging table columns
              Level 1
              Let me correct that a bit. What I actually used was:

              myTable.cells.item(c + ":" + r);

              where c and r and numbers and so can be derived from loop variables.

              Dave
              • 4. Re: [JS CS3] Merging table columns
                Peter Kahrel Adobe Community Professional & MVP
                Interesting -- thanks.

                Peter
                • 5. Re: [JS CS3] Merging table columns
                  Level 1
                  Thanks to both of you. I'll try both of your suggestions and see how much faster I can make my script.

                  One more question - in your experience, do scripts seem to get bogged down with large tables? For example, my table script was running on my 120 page table for around 12 hours and still wasn't finished. But, when I cut the table down to 25 pages, the script completed in under an hour.

                  I thought the change in the time it would take to run would be proportional, but it doesn't seem to be. I don't think the loops get stuck running indefinitely, but I could be wrong.

                  Thanks again!
                  • 6. Re: [JS CS3] Merging table columns
                    Level 1
                    Are you doing anything about the undo queue in your script? As that gets longer and longer it can really bog down a script.

                    I usually have something like this in my main loop:
                    if (j % 100 == 0) {
                    
                      myDoc.save(File(myFullName));
                    }
                    where j is the main loop counter.

                    Dave
                    • 7. Re: [JS CS3] Merging table columns
                      Level 1
                      I've just done some time testing with CS4 and found the following:
                      table = app.documents[0].stories[0].tables[0];
                      
                      start = new Date();
                      for (var n = 0; 100 > n; n++) {
                        cells = table.cells;
                        for (var j = 0; cells.length > j; j++) {
                          cells[j].contents = "James";
                        }
                      }
                      end = new Date();
                      alert(end - start);
                      takes just about the same time to run as:
                      table = app.documents[0].stories[0].tables[0];
                      
                      start = new Date();
                      rowCount = table.rows.length;
                      columnCount = table.columns.length;
                      for (var n = 0; 100 > n; n++) {
                        for (var c = 0; columnCount > c; c++) {
                          for (var r = 0; rowCount > r; r++) {
                            table.cells.item(c + ":" + r).contents = "Harry";
                          }
                        }
                      }
                      end = new Date();
                      alert(end - start);
                      While this version takes about half as long again:
                      table = app.documents[0].stories[0].tables[0];
                      
                      start = new Date();
                      rowCount = table.rows.length;
                      columnCount = table.columns.length;
                      for (var n = 0; 100 > n; n++) {
                        for (var c = 0; columnCount > c; c++) {
                          for (var r = 0; rowCount > r; r++) {
                            table.rows[r].cells[c].contents = "Harry";
                          }
                        }
                      }
                      end = new Date();
                      alert(end - start);
                      None of which is particularly surprising. But when I compared the following two scripts, I was astonished by the result:
                      table = app.documents[0].stories[0].tables[0];
                      
                      start = new Date();
                      rowCount = table.rows.length;
                      columnCount = table.columns.length;
                      for (var n = 0; 100 > n; n++) {
                        table.cells.everyItem().contents = "Harry";
                      }
                      end = new Date();
                      alert(end - start);

                      table = app.documents[0].stories[0].tables[0];
                      
                      start = new Date();
                      rowCount = table.rows.length;
                      columnCount = table.columns.length;
                      for (var n = 0; 100 > n; n++) {
                        table.cells.itemByRange(0, -1).contents = "George";
                      }
                      end = new Date();
                      alert(end - start);
                      The latter, using itemByRange was about a third faster than using everyItem(). 1800 milliseconds to 2700 on a 4 x 10 table.

                      Dave