• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Change text color in tables! …

LEGEND ,
Nov 30, 2016 Nov 30, 2016

Copy link to clipboard

Copied

Hi Scripters,

I'm trying to change color of the text in some rows but not all! As:

Capture d’écran 2016-11-30 à 22.35.13.png

Capture d’écran 2016-11-30 à 22.37.07.png

… with this code:

var

myDoc = app.activeDocument, 

myTables = myDoc.stories.everyItem().tables.everyItem().getElements(); 

 

for ( var t = 0 ; t < myTables.length; t++ ) 

        var myRows = myTables.rows;        

        for ( var r  = 1 ; r  < myRows.length; r += 2 ) 

        { 

                   var myCells = myRows.cells;                   

                   for ( var c = 0 ; c < myCells.length; c++ ) 

                   { 

                    myCells.contents.fillColor = myDoc.colors.itemByName("Blue");

                   } 

        }

}

… But, of course, it doesn't work!

As usual, thanks for your help! 

(^/)

TOPICS
Scripting

Views

3.6K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Nov 30, 2016 Nov 30, 2016

Copy link to clipboard

Copied

… Apparently, my error is at line 13. To be corrected as:

                    myCells.texts[0].fillColor = myDoc.colors.itemByName("Blue");

… But I find this script very slow! 

Is there a different writing to make it faster!

Thanks again! 

(^/)

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Nov 30, 2016 Nov 30, 2016

Copy link to clipboard

Copied

This is probably quicker (it's certainly quicker to type):

app.findGrepPreferences = app.changeGrepPreferences = null;

app.findGrepPreferences.fillColor = 'Black';

app.changeGrepPreferences.fillColor = 'Blue';

app.documents[0].stories.everyItem().tables.everyItem().changeGrep();

Peter

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Nov 30, 2016 Nov 30, 2016

Copy link to clipboard

Copied

Hi Peter,

Totally right! [ ] … if I wanted to change all "Red" text in "Blue"! …

But it's more complex: To simplify, I've not included a header row, but here I want to change only the "even" rows.

That's why I used 3 "for" loops [see the second one especially]! … surely the reason of the script slowness.

(^/)

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Nov 30, 2016 Nov 30, 2016

Copy link to clipboard

Copied

Hi Obi-wan,

what does slow mean? How many seconds for how many tables with how many rows?

There is an faster approach, but you'll need in advance to know the maximum number of rows of all the tables of your document.

Getting that value needs some time for calculation. That would be the "overhead" so to speak. But from then on its much faster than looping every row of every table.

On an old MacBook Pro from late 2008 with only 4 GB of RAM and InDesign CS6 with about 1200 rows in total—maximum rows of one table was: 1000—the script below took about 34 seconds to finish:

var startTime = Date.now();

var rowsMax = 0;

app.scriptPreferences.userInteractionLevel = UserInteractionLevels.interactWithAll;

app.doScript

    (

   

    colorTextOfEverySecondRow,

    ScriptLanguage.JAVASCRIPT,

    [],

    UndoModes.ENTIRE_SCRIPT,

    "Color text of every second row in document"

   

    );

var endTime = Date.now();

var elapsedTimeInSeconds = ((endTime - startTime)/1000);

$.writeln(elapsedTimeInSeconds+"\t"+"Sec."+" with rowsMax: "+rowsMax);

function colorTextOfEverySecondRow()

{

    var doc = app.documents[0];

    var color = doc.colors.itemByName("Blue");

    // Some preprocessing of the maximum number of rows:

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

    var tablesLength = tables.length;

    for(var n=0;n<tablesLength;n++)

    {

        var currentRowsLength = tables.rows.length;

        if(currentRowsLength > rowsMax){rowsMax = currentRowsLength};

    };

    // And here a demonstration of the power of everyItem()

    tables = doc.stories.everyItem().tables.everyItem();

    for(var n=1;n<rowsMax;n=n+2)

    {

        tables.rows.cells.everyItem().texts.everyItem().fillColor = color;

    };

   

    return rowsMax;

};

Note: No header or footer rows were defined in the tables.

I tested your code with my sample.

It took about 192 seconds to finish.

See also Marc Autret on everyItem() :

Indiscripts :: On ‘everyItem()’ – Part 1

Indiscripts :: On ‘everyItem()’ – Part 2

Regards,
Uwe

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 01, 2016 Dec 01, 2016

Copy link to clipboard

Copied

Uwe,

To speed things up with everyItem() you'd do it on the rows as well -- something like this:

tables = doc.stories.everyItem().tables.everyItem();

for (i = tables.length-1; i >= 0; i--) {

  rows = tables.rows.everyItem().getElements();

  for (j = rows.length-1; j >= 0; j--) {

      cells = rows.cells.everyItem().getElements();

      for (k = cells.length-1; k >= 0; k--) {

        // do something

      }

  }

}

P.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 01, 2016 Dec 01, 2016

Copy link to clipboard

Copied

Hi Peter,

yes, that would benefit Obi Wan's version of the script.

In my script I'd like to access the rows by index for every table in the document directly.
And by index I mean the individual index of the row in context with the individual table.

If I'd used getElements() I needed to loop every table individually.


And since every second row of a single table should be accessed starting with the second row of every table—we cannot know if a table has an even or an odd number of rows—I cannot loop through an array like that:

doc.stories.everyItem().tables.everyItem().rows.everyItem().getElements();

Instead I do it with:

doc.stories.everyItem().tables.everyItem().rows[ n ]

Example:

Have a document with three tables. One with 2 rows, one wih 7 rows and one with 5 rows.

I want to access the seventh row of all tables, I could do it like that:

doc.stories.everyItem().tables.everyItem().rows[6]

Regardless if there are any tables in the document with less than 7 rows.

Regards,

Uwe

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 01, 2016 Dec 01, 2016

Copy link to clipboard

Copied

Yes, ok. Anyway, the message is to use everyItem().getElements() wherever you can, especially in tables.

P.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Dec 01, 2016 Dec 01, 2016

Copy link to clipboard

Copied

Hi Obi,

May the below code also useful for you,

myDoc = app.activeDocument,   
myTables = myDoc.stories.everyItem().tables.everyItem().getElements();   
  
for ( var t = 0 ; t < myTables.length; t++ )   
{   
        var myRows = myTables.rows;     
        for ( var r  = 1 ; r  < myRows.length; r = r +2 )   
        {   
               var myCells = myRows.cells;                
               for ( var c = 0 ; c < myCells.length; c++ )   
               {   
                myCells.texts[0].fillColor = myDoc.colors.itemByName("Blue"); 
               }   
       

Thanks in Advance

Siraj

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Mentor ,
Dec 01, 2016 Dec 01, 2016

Copy link to clipboard

Copied

Hi Uwe,

Laubender napisał(-a):

...

And since every second row of a single table should be accessed starting with the second row of every table—we cannot know if a table has an even or an odd number of rows—I cannot loop through an array like that:

  1. doc.stories.everyItem().tables.everyItem().rows.everyItem().getElements();

....

I think you can ==> checking row's index which is related to a parent (table), so

mDoc = app.activeDocument,

mRows = mDoc.stories.everyItem().tables.everyItem().rows.everyItem().getElements(),

cRow, mColor = mDoc.swatches.item("Blue");

while (cRow = mRows.pop())

     if(cRow.index%2)

          cRow.cells.everyItem().texts.everyItem().fillColor = mColor;

Jarek

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 01, 2016 Dec 01, 2016

Copy link to clipboard

Copied

Hi Jarek,

very good.

Just tested your idea on my sample document.
Surprisingly it was a bit slower than my script, but not much:

41 vs 37 seconds

Did more than one test with both ideas.

The values are on average.

Thanks,
Uwe

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 01, 2016 Dec 01, 2016

Copy link to clipboard

Copied

> while (cRow = mRows.pop())

This is one of the most expensive ways to go through an array. Really.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Mentor ,
Dec 01, 2016 Dec 01, 2016

Copy link to clipboard

Copied

Hi all,

I made some test based on my code and Uwe's timer ==>  changing loops inside function.

A few tables in 1 story - total 2k rows, max 1500).

4 tests (repeated few times to average) where loops are alike:

1. while(cRow = mRows.pop())     ==> time ~8,3 s

2. while(len--)     //  ==>    time ~8,25 s

3. for (var k = 0; k < len; k++)     ==> time ~43 s

4. for (var k = len-1; k >=0; k--)     ==> time ~8,3 s

It looks like - in this case - most important is backward or forward direction of changes

Jarek

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 02, 2016 Dec 02, 2016

Copy link to clipboard

Copied

Hi Jarek,

interesting…

I did my sample document with several stories and used a for loop with my first tests on your idea.

Don't know if you did that, but I think it's important to restart InDesign before starting a new test.

Unfortunately I did not do that with my first tests.

I tested again on CS6 v8.1.0 on Mac OSX 10.6.8 with 4GB RAM.
So here are some new figures:

1. Direct accessing the rows with my script in answer # 4:

~31.0 s

2. Your index method and a for-loop forward through the rows array gathered by getElements() :

~29.3 s

3. Your index method and a for-loop backward through the rows array gathered by getElements() :

~27.8 s

It's not as dramatic as your figures are showing, but the main difference in my tests is that I used several stories and not just one. We should exchange test documents to get better insight.

And I should repeat my tests on a machine with more RAM.

Thanks,
Uwe

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 02, 2016 Dec 02, 2016

Copy link to clipboard

Copied

Forgot to mension the new figure with running Obi-Wan's script after restarting InDesign:

~182.8 s

Speaking of Obi-Wan:

How are your speed results, Obi-Wan?

Are you still following?

Regards,
Uwe

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Dec 02, 2016 Dec 02, 2016

Copy link to clipboard

Copied

LATEST

Aha! Of course I'm here and read all your comments!

Too glad to see your answers and learn such a lot!

As you see, i'm able to write scripts that work sometimes but the more interesting for me is to know and understand (so learn great) how you think and write and why my script time is x 5! 

i'll test all your ways this afternoon!

(^/)

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines