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

Script: conditional formatting of table cells but exclude header row

Community Beginner ,
Jun 26, 2020 Jun 26, 2020

Hello all,

 

I've got a script set up to apply a fill color to cells within a table based on the value found within each cell.

 

It was working fine; however, I just added a piece to it in attempt to have the script exclude the header row. I've already spent hours adapting the original script to my needs, but unfortunately this is where my knowledge, patience, and Google-fu ends.

 

The error I'm getting is this:

 

  • Error Number: 55
    Error String: Object does not support the property or method 'rowType'
    Engine: main
    File: /Users/c059822/Library/Preferences/Adobe InDesign/Version 14.0/en_US/Scripts/Scripts Panel/stoplight-cell-colors.jsx
    Line: 1
    Source: app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, "Conditional cell formatting"); function main()

 

And here's the script in its current state:

 

app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, "Conditional cell formatting"); function main() 
{
	sel = app.selection[0];
	if (sel.constructor.name != "TextFrame")
	{
		alert("Please select the textframe that contains the table.");
		exit();
	}

	// create color swatches
	var mint = swatchCreator("First Quartile - Mint", [51,0,32,0]);
	var cream = swatchCreator("Second Quartile - Cream", [2,0,45,0]);
	var peach = swatchCreator("Third Quartile - Peach", [0,42,36,0]);
  	var dkred = swatchCreator("Fourth Quartile - Thrivent Dark Red", [0,100,55,23]);
	tables = sel.tables;
	for (var i = 0; i < tables.length; i++)
	{
		// ---------Here's the part I added----------
		var bodyRows = (tables[i].rows.rowType == RowTypes.BODY_ROW);
		for (var r = 0; r < rows.length; r++)
		{
			// ----------This var used to call on the "for" that looks at the table, above the part I added------------
			var cells = bodyRows[r].cells;
			for (var c = 0; c < cells.length; c++)
			{
				var cellValue = parseFloat(cells[c].texts[0].contents);
				if (cellValue <= 25)
				{
					cells[c].fillColor = mint;
					continue;
				}
				if (cellValue >= 26 && cellValue <= 50)
				{
					cells[c].fillColor = cream;
					continue;
				}
				if (cellValue >= 51 && cellValue <= 75)
				{
					cells[c].fillColor = peach;
					continue;
				}
      
				if (cellValue > 76)
				{
					cells[c].fillColor = dkred;
				}
			}
		}
	}
}

function swatchCreator(colorname, values) 
{
	var swatch = app.activeDocument.colors.item(colorname);
	if (!swatch.isValid)
	{
		swatch = app.activeDocument.colors.add({
		name: colorname,
		model: ColorModel.PROCESS,
		space: ColorSpace.CMYK,
		colorValue: values
		});
	}
	return swatch;
}

 

Any help I can get would be majorly appreciated! Also, I'm new to the forum, so forgive me for any formatting, subject phrasing, etiquette, etc. that is missing here.

TOPICS
Bug , How to , Scripting
2.0K
Translate
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

correct answers 1 Correct answer

Community Expert , Jun 26, 2020 Jun 26, 2020

The idea in the code snippet shared by LSH_246 is correct but i see that even the row variable is not defined in the code, so foe the sake of completion i am posting the full version of the code that i think will serve the purpose

app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, "Conditional cell formatting"); function main() 
{
	sel = app.selection[0];
	if (sel.constructor.name != "TextFrame")
	{
		alert("Please select the textframe that contains the table.");
	
...
Translate
Community Expert ,
Jun 26, 2020 Jun 26, 2020

Hi Ryan,

 

The line that has the error is the following

var bodyRows = (tables[i].rows.rowType == RowTypes.BODY_ROW);

 

Here the issue is that you are trying to access the property rowType on the object rows which is a collection of rows. This property exits on a row object and not on the collection of rows. See the documentation of row object below

https://www.indesignjs.de/extendscriptAPI/indesign-latest/#Row.html

 

-Manan

 

Translate
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
Participant ,
Jun 26, 2020 Jun 26, 2020

You're looking for `rowType` on the collection of rows, rather than on the individual row.  Try starting your for loop like this instead (and delete the line immediately preceding the for loop):

 

for (var r = 0; r < rows.length; r++)
{
    if (rows[r].rowType != RowTypes.BODY_ROW) {
        continue;
    }
    var cells = rows[r].cells;

 

[edit - Manan beat me to it by 2 minutes! Leaving this code snippet though in case it's helpful.]

Translate
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 Beginner ,
Jun 26, 2020 Jun 26, 2020

Thank you so much! You and Manan are so fast! You were both right, technically, but he already tagged you as correct, so I guess we'll let you keep it? 🙂

Translate
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 ,
Jun 26, 2020 Jun 26, 2020

The idea in the code snippet shared by LSH_246 is correct but i see that even the row variable is not defined in the code, so foe the sake of completion i am posting the full version of the code that i think will serve the purpose

app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, "Conditional cell formatting"); function main() 
{
	sel = app.selection[0];
	if (sel.constructor.name != "TextFrame")
	{
		alert("Please select the textframe that contains the table.");
		exit();
	}

	// create color swatches
	var mint = swatchCreator("First Quartile - Mint", [51,0,32,0]);
	var cream = swatchCreator("Second Quartile - Cream", [2,0,45,0]);
	var peach = swatchCreator("Third Quartile - Peach", [0,42,36,0]);
  	var dkred = swatchCreator("Fourth Quartile - Thrivent Dark Red", [0,100,55,23]);
	tables = sel.tables;
	for (var i = 0; i < tables.length; i++)
	{
		// ---------Here's the part I added----------
		//var bodyRows = (tables[i].rows.rowType == RowTypes.BODY_ROW);
		for (var r = 0; r < tables[i].rows.length; r++)
		{
			if(tables[i].rows[r].rowType != RowTypes.BODY_ROW)
				continue;
			// ----------This var used to call on the "for" that looks at the table, above the part I added------------
			var cells = tables[i].rows[r].cells;
			for (var c = 0; c < cells.length; c++)
			{
				var cellValue = parseFloat(cells[c].texts[0].contents);
				if (cellValue <= 25)
				{
					cells[c].fillColor = mint;
					continue;
				}
				if (cellValue >= 26 && cellValue <= 50)
				{
					cells[c].fillColor = cream;
					continue;
				}
				if (cellValue >= 51 && cellValue <= 75)
				{
					cells[c].fillColor = peach;
					continue;
				}
      
				if (cellValue > 76)
				{
					cells[c].fillColor = dkred;
				}
			}
		}
	}
}

function swatchCreator(colorname, values) 
{
	var swatch = app.activeDocument.colors.item(colorname);
	if (!swatch.isValid)
	{
		swatch = app.activeDocument.colors.add({
		name: colorname,
		model: ColorModel.PROCESS,
		space: ColorSpace.CMYK,
		colorValue: values
		});
	}
	return swatch;
}

 

-Manan

Translate
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 Beginner ,
Jun 26, 2020 Jun 26, 2020

Thank you! This was easy to just copy and paste into the file. It works!!

Translate
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 ,
Jun 27, 2020 Jun 27, 2020
LATEST

Hi Ryan,

you could also check the number of header rows before doing the loop with headerRowCount :

// Text frame with table selected:
var table = app.selection[0].tables[0];

var tableRowsArray = table.rows.everyItem().getElements();
var tableRowsArrayLength = tableRowsArray.length;

var startLoopAt = table.headerRowCount - 1;

for( var n=startLoopAt ; n<tableRowsArrayLength; n++ )
{
// DO YOUR THING
};

 

And if you do not want affect footer rows you can restrict the loop even more.

You perhaps guessed it, there is a footerRowCount property with tables as well.

 

Regards,
Uwe Laubender

( ACP )

Translate
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